2016-04-12 14 views
0

Ich verwende $ rootScope. $ On in einem Controller, um auf ein Ereignis zu hören, das von einem Modul ausgegeben wird, das ich verwende (angular-patiery). Es funktioniert, dass es das Ereignis bekommt & Ich kann Sachen auf den "Argumenten" durchführen. Aber ich möchte das Objekt args in eine Objektvariable schreiben, die außerhalb des Bereichs der Listener-Funktion deklariert ist. Ich kann nicht den folgenden Code an die Arbeit:

(function() { 
    'use strict'; 
    angular 
     .module('app') 
     .controller('searchSpeakersResultsCtrl', searchSpeakersResultsCtrl); 

     searchSpeakersResultsCtrl.$inject = ['$rootScope', '$scope']; 
     function searchSpeakersResultsCtrl($rootScope, $scope) { 
      var vm = $scope; 


      var pckry = {}; 
      var packeryEventListener = function (event, args) { 
       pckry = args; 
       console.log(pckry); 
      } 

      var unbind = $rootScope.$on('packeryInstantiated', packeryEventListener); 
      console.log(pckry); 
      vm.$on('$destroy', unbind); 

     } 
})(); 

Die console.log innerhalb der Listener-Funktion den richtigen Wert gibt, gibt die console.log außerhalb der Funktion das leere Objekt mit var pckry erstellt = {} ;.

Wie jedoch erwartet wird, aktualisiert die direkte Verwendung der Funktion packeryEventListener (nicht aus $ rootScope. $ On) den Wert von pckry außerhalb der Funktion packeryEventListener.

Was könnte ich vermissen? Scheint so, als ob die grundlegenden JavaScript-Variablen für den Umfang nicht funktionieren, wenn sie mit $ rootScope. $ On verwendet werden. Cheers, H.

+1

Ihr Problem hier ist einfach eines der Zeit: Das 'console.log', das ein leeres Objekt sieht, wird ausgelöst, bevor der Callback die Variable auffüllt. Denken Sie daran, dass angular eine sehr asynchrone Umgebung ist: Callbacks passieren immer später als Sie denken. – Duncan

+0

Duncan, wow! Ich wickelte die äußere console.log in einem Timeout und es hat funktioniert! $ Timeout (function() { \t \t \t \t console.log (pckry); \t \t \t}, 0); Also, kurze Frage: Was ist eine gute Art damit zu arbeiten? Muss ich den gesamten Code außerhalb der Listener-Funktion innerhalb eines Timeouts einbinden, oder? . . ? –

+0

oder verschieben Sie es in den Rückruf, oder lesen Sie Versprechen und beginnen Sie, sie überall zu verwenden. – Duncan

Antwort

0

Ihr Problem hier ist einfach eine der Timing: die console.log, die ein leeres Objekt sieht, bevor die ausgelöst Callback füllt die Variable auf. Denken Sie daran, dass angular eine sehr asynchrone Umgebung ist: Callbacks passieren immer später als Sie denken.

Das Einhüllen des Codes in einem $timeout() reicht hier möglicherweise aus, aber im Allgemeinen möchten Sie sicherstellen, dass der Code, der ein asynchron verwendet, nicht ausgeführt werden kann, bis der asynchrone Teil abgeschlossen ist. Das bedeutet normalerweise, dass etwas, das einen asynchronen Prozess startet, ein Versprechen geben sollte. Mit Versprechungen können Sie etwas ausführen lassen, wenn sie auflösen oder wenn sie .catch() abgelehnt werden oder Sie können sie auf verschiedene Arten wie $q.all() kombinieren, um auf mehrere abgeschlossene Dinge zu warten.

Beachten Sie, dass $timeout und $http auch Versprechen versprechen.

Sobald Sie ein Versprechen haben, können Sie auch nach der Auflösung des Versprechens, auch wenn es vor Wochen aufgelöst wurde, immer thePromise.then(function() {...}) als Wächter verwenden, um Code auszuführen. (Und denken Sie daran, dass, selbst wenn das Versprechen bereits gelöst wurde, der Rückruf immer noch asynchron aufgerufen wird, also erst, wenn Ihr anderer Code zurückgegeben wurde).

0

Ja, versuchen Wert in $ Umfang zu speichern und dann sehen, so etwas wie

(function() { 
'use strict'; 
angular 
    .module('app') 
    .controller('searchSpeakersResultsCtrl', searchSpeakersResultsCtrl); 

    searchSpeakersResultsCtrl.$inject = ['$rootScope', '$scope']; 
    function searchSpeakersResultsCtrl($rootScope, $scope) { 
     var vm = $scope; 


     var pckry = {}; 
     var packeryEventListener = function (event, args) { 
      $scope.pckry = args; 
      console.log($scope.pckry); 
     } 

     var unbind = $rootScope.$on('packeryInstantiated', packeryEventListener); 
     console.log($scope.pckry); 
     vm.$on('$destroy', unbind); 

    } 
})(); 
+0

vm.pckry anstelle von $ scope. aber ich benutze den vm überhaupt nicht. Die vm wird verwendet, wenn ControllerAs verwendet wird, und dann wird vm = this zugewiesen. –

+0

Ja, Sie müssen dies nicht tun, da Sie vm nur einen Bereich zuweisen, das ist es – pradeep1991singh

+0

Über die vm stuff: Ich folge dem Stil von ein paar anderen Code in dieser App von einigen anderen Entwicklern vor mir geschrieben , nur aus Gründen der Konsistenz an diesem Punkt, da es scheint, dass es nichts bewirkt. Nicht sicher, warum sie es so gemacht haben. –