2

コードが重い投稿で申し訳ありませんが、できるだけ多くのコンテキストを提供したかった. Angular.js アプリケーションでサービスを定義する際に問題が発生しています。サービスは、アプリケーション ( source )全体でシングルトンとして機能することになっているため、次の動作が発生することに非常に混乱しています。

app.jsファイルで、AmplitudeService Service と console.log(AmplitudeService)を実行します。これにより、AmplitudeService.js ファイル内で定義したすべてのメソッドを含むオブジェクトが出力されます。そのため、サービスを適切に使用して、期待どおりにイベントをログに記録できます。

ただし、header.js内で console.log(AmplitudeService) を実行すると、 Window オブジェクトが出力されます。そのため、Window には「logEvent」や「identifyUser」などの機能が含まれていないため、その場合はAmplitudeServiceを使用できません。

ありとあらゆる洞察をいただければ幸いです。

AmplitudeService.js (ソース)

注: 作成者の構文を確認すると、作成者はサービスの最後にオブジェクトを返します。私の調査では、Service 関数 ( source ) を定義するときに「this」キーワードを使用すること、および Factory の場合のようにオブジェクトを返す必要がないことを読んだので、それに応じて更新しました。

angular.module('AmplitudeService', [])
.service('AmplitudeService', 
['$amplitude', '$rootScope', 'amplitudeApiKey', '$location',
 function ($amplitude, $rootScope, amplitudeApiKey, $location) {

  this.init = function() {
    $amplitude.init(amplitudeApiKey, null);
    $amplitude.logEvent('LAUNCHED_SITE', {page: $location.$$path});
  }

  this.identifyUser = function(userId, userProperties) {
    $amplitude.setUserId(userId);
    $amplitude.setUserProperties(userProperties);
  }

  this.logEvent = function(eventName, params) {
    $amplitude.logEvent(eventName, params);
  }
}]);

angular-amplitude.js (ソース)

これにより、アプリケーション全体で「$amplitude」にアクセスできます

(function(){
var module = angular.module('angular-amplitude', ['ng']);

module.provider('$amplitude', [function $amplitudeProvider() {
    this.$get = ['$window', function($window) {
      (function(e,t){
        var r = e.amplitude || {};
        var n = t.createElement("script");
        n.type = "text/javascript";
      n.async = true;
      n.src = "https://d24n15hnbwhuhn.buttfront.net/libs/amplitude-2.2.0-min.gz.js";
      var s = t.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(n,s);
      r._q = [];

      function a(e){
        r[e] = function(){
          r._q.push([e].concat(Array.prototype.slice.call(arguments,0)));
        }
      }
      var i = ["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties"];
      for(var o = 0; o < i.length; o++){
        a(i[o])
      }
      e.amplitude = r
    }
      )(window,document);
      return $window.amplitude;
    }];
}]);
return module;
}());

App.js

angular.module('app', [
'ngRoute',
'angular-amplitude',
'AmplitudeService',
])

 .run(['AmplitudeService', function(AmplitudeService){
 console.log(AmplitudeService); // Outputs 'Object {}'
 AmplitudeService.init();
 AmplitudeService.logEvent('LAUNCHED_SITE');
 console.log(AmplitudeService); // Outputs 'Object {}'
 }])

Header.js

angular.module('app.common.header', [])
.controller('HeaderCtrl', [ '$rootScope', '$scope', '$location', '$scope', '$route', '$window', 'AmplitudeService', function($rootScope, $scope, $location, $route, $window, AmplitudeService){

$scope.goToSearch = function(term) {
$location.path('/search/' + term);
 console.log(AmplitudeService); // Outputs 'Window {}'
};
}]);
4

1 に答える 1

3

コントローラーに注入しているように見え$scope、変数の予期しないマッピングが発生します

angular.module('app.common.header', [])
.controller('HeaderCtrl', [ '$rootScope', '$scope', '$location', **'$scope'**, '$route', '$window', 'AmplitudeService', function($rootScope, $scope, $location, $route, $window, AmplitudeService){

$scope.goToSearch = function(term) {
$location.path('/search/' + term);
 console.log(AmplitudeService); // Outputs 'Window {}'
};
}]);

余談ですが、コントローラーを定義するときに、この形式の方がはるかに読みやすく、操作しやすいことがわかります。

angular
  .module('app.common.header', [])
  .controller('HeaderCtrl', headerController);

headerController.$inject = [ '$rootScope', '$scope', '$location', '$route', '$window', 'AmplitudeService']

function headerController($rootScope, $scope, $location, $route, $window, AmplitudeService){
  $scope.goToSearch = function(term) {
    $location.path('/search/' + term);
    console.log(AmplitudeService); // Outputs 'Window {}'
  };
}
于 2016-05-24T16:42:12.390 に答える