2016-05-24 11 views
2

Entschuldigung für den Code schweren Post, aber ich wollte so viel Kontext wie möglich bieten. Ich habe ein Problem bei der Definition eines Dienstes in meiner Angular.js-Anwendung. Dienste sollen als Singletons in einer Anwendung (source) fungieren, so dass ich sehr verwirrt bin, das folgende Verhalten zu erhalten.AngularJS Service nicht als Singleton

In meinem app.js Datei, betreibe ich meine AmplitudeService Dienst und console.log (AmplitudeService). Dies gibt ein Objekt mit allen Methoden aus, die ich in meiner AmplitudeService.js-Datei definiert habe. Daher kann ich den Service ordnungsgemäß verwenden und Ereignisse protokollieren wie erwartet.

Wenn ich jedoch console.log (AmplitudeService) innerhalb meiner header.js, gibt es mein Window-Objekt aus. Daher enthält das Fenster keine Funktionen wie "logEvent", "identifyUser" usw., so dass AmplitudeService in diesem Fall nicht verwendbar ist.

Ich würde jede und jede Einsicht zu schätzen wissen!

AmplitudeService.js (source)

Hinweis: Wenn Sie die Syntax des Autors überprüfen, er gibt ein Objekt am Ende seines Dienstes. In meiner Forschung habe ich gelesen, das Schlüsselwort "this" zu verwenden, wenn ich Service-Funktionen definiere (source), und dass Sie kein Objekt wie bei einer Factory zurückgeben müssen, also habe ich es entsprechend aktualisiert.

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); 
    } 
}]); 

Winkel amplitude.js (source)

Dies ermöglicht den Zugriff auf "$ Amplitude" in der gesamten Anwendung

(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 {}' 
}; 
}]); 

Antwort

3

Sieht aus wie Sie $scope in Ihrem Controller injizieren, das Unerwartete Zuordnung der variablen

verursacht
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 {}' 
}; 
}]); 

als Nebenbei bemerkt, wenn dieses Format viel einfacher finden/Arbeit zu lesen mit bei der Definition von Controllern

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 {}' 
    }; 
} 
+0

Ich denke, ich brauche $ Scope, aber ich könnte falsch liegen. Alle meine Funktionen (die ich gekürzt habe, um die Menge an Code in diesem Beitrag zu reduzieren) innerhalb von Header.js sind als $ scope-Funktionen aufgeführt. Zum Beispiel würde $ scope.goToSearch (Begriff) auf meine Suchseite gehen und nach dem Begriff suchen. Diese Funktion wird im HTML mit ng-submit = "goToSearch (term)" aufgerufen. – zomp

+0

Ich habe die $ scope-Injektion entfernt, aber jetzt habe ich 7 undefined Funktionen in diesem Controller. Irgendwelche anderen Vorschläge? Ich schätze den vorherigen Kommentar. – zomp

+2

Sie haben '$ scope' zweimal injiziert - schauen Sie, wo ich in Ihrem Beispiel den '**' $ scope '**' hinzugefügt habe (erstes Codebeispiel). Entferne diese Definition und du solltest gut gehen. –