2

I've read many answers to this question but I just don't get it. Where does the promise go? I made a simple factory with an async call to a cloud database:

app.factory('asyncFactory', function() {

  let toController = function() {

    firebase.database().ref('en').once('value') // get the array from the cloud database
    .then(function(snapshot) { // take a snapshot
      console.log(snapshot.val()); // read the values from the snapshot
      return snapshot.val(); // this returns later
    });

    return 47 // this returns immeadiately
  };

  return {
    toController: toController // why is this necessary?
  }

});

I call it from my controller:

$scope.words = asyncFactory.toController();
console.log($scope.words);

Here's the response:

response

As you can see, 47 returns to the controller immediately. If I comment out return 47 then the factory returns undefined. Later the async data logs but doesn't return to the controller. I use promises every day but I can't figure out where the promise goes.

Second question: do I need the line toController: toController ? Can I get rid of it?

Thanks!

1
  • 1
    The promise doesn't go anywhere because instead of returning it, you're returning 47. Read blog.ninja-squad.com/2015/05/28/angularjs-promises. Regarding "do I need the line toController: toController", well, no, but then your service would have no method at all, and would be really useless. Commented Sep 16, 2017 at 21:45

2 Answers 2

2

To use the results from the firebase call in the controller, the factory method needs to return a promise:

app.factory('asyncFactory', function($q) {    
  return {
    toController: toController
  };

  function toController() {

    var es6promise = firebase.database().ref('en').once('value');

    var qPromise = $q.when(es6promise)
      .then(function(snapshot) { // take a snapshot
        console.log(snapshot.val()); // read the values from the snapshot
        return snapshot.val(); // this returns later
    });

    return qPromise;
  };

});

Because the firebase .once method returns an ES6 promise, that promise needs to be brought into the AngularJS framework by converting it to a $q Service promise with $q.when. Only operations which are applied in the AngularJS execution context will benefit from AngularJS data-binding, exception handling, property watching, etc.

In the controller, use the .then method to extract the data after it returns from the server:

var qPromise = asyncFactory.toController();

qPromise.then(function(data) {
    console.log(data)
    $scope.words = data;
});

The factory function immediately returns a promise. When the data arrives from the server, the data will be placed on $scope.

Sign up to request clarification or add additional context in comments.

Comments

1

Well toController is eating the promise for itself. ( whenever you call .then(), it means you are waiting for promise), Try this

app.factory('asyncFactory', function() {
  let toController = function() {
   var deferred = $q.defer();
    firebase.database().ref('en').once('value') // get the array from the cloud database
    .then(function(snapshot) { // take a snapshot
      console.log(snapshot.val()); // read the values from the snapshot
      return deferred.resolve(snapshot.val()); // this returns later
    });

    //return deferred.resolve(47) // this returns immeadiately
  };

  return {
    toController: toController // why is this necessary?
  }

});

If you don't want this line

return { toController: toController // why is this necessary? }

app.factory('asyncFactory', function() {

  return {
   var deferred = $q.defer();

    firebase.database().ref('en').once('value') // get the array from the cloud database
    .then(function(snapshot) { // take a snapshot
      console.log(snapshot.val()); // read the values from the snapshot
      return deferred.resolve(snapshot.val()); // this returns later
    });

    //return deferred.resolve(47) // this returns immeadiately
  };

})

1 Comment

My controller is getting "undefined" returned from the factory, i.e., it's not waiting for the async response. But thanks for answering my second question!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.