简体   繁体   中英

$scope variable not set from Factory

I'm new to Angular I'm trying to pass some data into a controller from a factory method. I can see the the data when I log the Factory variable. I try to pass the data to a $scope variable ($scope.song) but outside of the method, the $scope variable is undefined. What am I doing wrong? Code Below:

.controller('MessagesCtrl', function($scope, FetchSong){
FetchSong.nextSong('audio-message')
  .then(function(response){
    $scope.song = FetchSong.queue;
    console.log(FetchSong.queue);    //logs the data 
    console.log(response.data);     //also logs the data
});
console.log($scope.song);   //returns undefined
})

Here is the timeline of the execution of the code:

// t0: ask the service for the next song: the service sends an HTTP 
// request (I guess) to get it
FetchSong.nextSong('audio-message')
  .then(function(response){

    // t0 + 3 seconds: the http message has reached the server 10,000 
    // miles away from here, the server got the next song from its 
    // database, and sent it back. It took some time to travel the 10,000
    // miles in the other direction, but it finally arrived, so we can 
    // store it in the scope
    $scope.song = FetchSong.queue;
    console.log(FetchSong.queue);    //logs the data 
    console.log(response.data);     //also logs the data
});

// t0 + 1 microsecond: try to print the next song
console.log($scope.song);   //returns undefined

The key thing to realize is that, every time a service returns a promise on which you call then() and pass a callback function, it means it can't just return the value now. It returns... a promise that will be resolved later, because some work needs to be done asynchronously before the result can be available.

So, printing the result immediately after you called the service and got the promise back will never work. The result is only available once the callback function has been called, later.

I have written a blog post explaining how promises work and how to avoid traps like the ones you fell into.

The issue is, you try to access $scope.song before it been assigned value in FetchSong.nextSong promise callback, since promise is asynchronous, all code related to a promise return data should be put in its callback, see doc :

 .controller('MessagesCtrl', function($scope, FetchSong){

      FetchSong.nextSong('audio-message').then(function(response){

          $scope.song = FetchSong.queue;
          console.log(FetchSong.queue);    //logs the data 
          console.log(response.data);     //also logs the data

      }).then(function(){

          console.log($scope.song);   //returns FetchSong.queue

      });

 })

you should use $scope.$apply(); see more in https://docs.angularjs.org/api/ng/type/ $rootScope.Scope

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM