9
votes

i have problems when it comes to $http promises in angularjs. i am doing this in my service: (the getSomething function should chain two promises)

the second function uses a external callback function!

app.service('blubb', function($http, $q) {

  var self = this;

  this.getSomething = function(uri, data) {
    return self.getData(uri).then(function(data2) {
      return self.compactData(uri, data2);
    });
  };

  this.getData = function(uri) {
    var deferred = $q.defer();
    $http.get(uri).success(function(data) {
      deferred.resolve(data);
    }).error(function() {
      deferred.reject();
    });

    return deferred.promise;
  };

  this.compactData = function(uri, data) {
    var deferred = $q.defer();
    /* callback function */
      if(!err) {
        console.log(compacted);
        deferred.resolve(compacted);
      } else {
        console.log(err);
        deferred.reject(err);
      }
    /* end of function */

    return deferred.promise;
  };
});

when i use the service in my controller it doesn't output the console.log:

blubb.getSomething(uri, input).then(function(data) {
  console.log(data)
});

edit: if i define the callback function by myself in 'compactData' it works, but i am using "jsonld.compact" from https://raw.github.com/digitalbazaar/jsonld.js/master/js/jsonld.js and THIS doesn't work!

    jsonld.compact(input, context, function(err, compacted) {
      if(!err) {
        console.log(compacted);
        deferred.resolve(compacted);
      } else {
        deferred.reject('JSON-LD compacting');
      }
    });

i am getting the console.log output in jsonld.compact but the resolve doesn't work and i don't know why..

it only works with $rootScope.$apply(deferred.resolve(compacted));

4
Unless compacted is defined somewhere and is in scope, then you probably want to change deferred.resolve(compacted); to deferred.resolve("compacted");, and probably the same for err.Beetroot-Beetroot
sry, compacted and err are defined by the callback function! there is also the right output from console.log(compacted) in this function, but not in the 'chained' getSomething function.Betty St
If it still doesn't work, then test blubb.getData() and blubb.compactData() separately before testing blubb.getSomething().Beetroot-Beetroot
i used $rootScope.$apply and it works! (see stackoverflow.com/questions/14529354/…) BUT i am getting this error: Error: $digest already in progressBetty St
Kindly share complete fiddle because there are so many things not given in the questionAjay Beniwal

4 Answers

5
votes

I'm using chaining promises like this:

            $http.get('urlToGo')
                .then(function(result1) {
                    console.log(result1.data);
                    return $http.get('urlToGo');
                }).then(function(result2) {
                    console.log(result2.data);
                    return $http.get('urlToGo');
                }).then(function(result3) {
                    console.log(result3.data);
                });
1
votes

Chaining promises works here : jsfiddle

In your implementation, if $http.get or compactData goes wrong your console.log(data) will not be call.

You should maybe catch errors :

    blubb.getSomething(uri, input).then(function(data) {
       console.log(data);    
    }, function(err) {
       console.log("err: " + err);
    });
1
votes

Whenever you use an external (external to AngularJS) callback that runs in a new turn/tick, you have to call $apply() on the appropriate scope after it has been invoked. This lets AngularJS know it has to update. You'll probably want to make sure you're only calling it once -- after all of the promises have been resolved. As an aside, jsonld.js provides a promises/future API, so if you're already using promises, you don't have to do that wrapper code above. Instead you can do:

var promisesApi = jsonld.promises();
var promise = promisesApi.compact(input, context);

// do something with the promise
0
votes

I would suggest you to use a Factory instead of a service.

Just return the function from the factory and use it in your controller