Tyler Palmer
Tyler Palmer

Reputation: 11

Angularfire $firebaseArray.$add() returning undefined when called in external service, not a promise as expected

I have set up a small application using Angular + AngularFire + Firebase. Here are my versions:

Angular: 1.4.3 Firebase: 2.2.4 AngularFire: 1.1.3

I have multiple angular services: -Trip Service: connects directly to firebase and is the only service involved that uses the angularfire objects ($firebaseArray, $firebaseObject). This is the code:

trvlApp.service('tripSvc', function($firebaseArray, $firebaseObject, constants) {

  // create ref to /trips data in firebase. base url stored in constants 
  var rootRef = new Firebase(constants.fbBaseUrl + '/trips/');

  var getTripsArray = function(uid) {
    return $firebaseArray(rootRef.child(uid));
  };

  this.addTripForUser = function(uid, tripObj) {
    var trips = getTripsArray(uid); // get trips for uid
    trips.$loaded() // when trips array is loaded
    .then(
      function(response) {
        return trips.$add(tripObj); // return promise of adding trip
      }
    );
  };

-mytripsOps: Another service that pulls/processes data from tripSvc and passes data to a controller. This service does not use $firebaseObject or $firebaseArray. The relevant method in that service looks like this:

trvlApp.service('mytripsOps', function(tripSvc) {

  this.addCompletedTripForUser = function(uid, tripObj) {
    tripSvc.addTripForUser(uid, tripObj) // should return promise, instead returns undefined
      .then(
        function(response) {
          console.log("Completed trip added.", response);
        }
      );
  };
});

In the latter service, when the .then() method tries to execute, a "cannot read .then property of undefined" error is thrown, implying that the calling of tripSvc.addTripForUser within mytripsOps does not return a promise as expected.

A few other notes: -The $add method returns a promise correctly when called within tripSvc itself. -I can create a workaround for this by creating my own promise within tripSvc.addTripForUser and resolving it when $add resolves, but this seems to be excessive. -Within tripSvc.addTripForUser, I also tried first calling trips.$add(tripObj), then returning $trips.$save(), but this yielded the same result. -Other methods in tripSvc return angularfire promises (e.g. return $tripObj.$save()), and those promises do get returned when the methods are called in other services.

So, the question is: why is "undefined" being returned when I call tripSvc.addTripForUser within mytripsOps, rather than a promise? AngularFire's documentation says pretty clearly that $add() should return a promise:

https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebasearray-addnewdata

Thanks for the help ahead of time, I'm still relatively new to Angular and Firebase and this one has been driving me nuts.

Upvotes: 0

Views: 452

Answers (1)

Tyler Palmer
Tyler Palmer

Reputation: 11

After some tinkering, I found the solution. In order for the promise to be returned from the addTripForUser function in tripSvc, I need to return the entire $trips.loaded block:

 this.addTripForUser = function(uid, tripObj) {
    var trips = getTripsArray(uid); // get trips for uid
 // NOTE THE NEW RETURN ON THE LINE BELOW   
 return trips.$loaded() // when trips array is loaded
    .then(
      function(response) {
        return trips.$add(tripObj); // return promise of adding trip
      }
    );
  };

By returning the entire trips.$loaded() block, I was able to access the promise returned by addTripForUser in the separate mytripsOps service and call .then() on it.

Upvotes: 1

Related Questions