9

I want to chain some promises that are returned by services. This works, as long as some of the methods that return the promises, doesn't require additional parameters. This is my example:

var first = function() {
  var d = $q.defer();
  $timeout(function() {
    d.resolve("first resolved")
  }, 100)
  return d.promise;
};

var second = function(val) {
  console.log("value of val: ", val);
  var d = $q.defer();
  $timeout(function() {
    d.resolve("second resolved")
  }, 200)
  return d.promise;
};

first().then(second).then(function(value) {
  console.log("all resolved", value);
});

This works as expected. But what if my service second needs an additional parameter val to do it's job? With the method above the value of val is "first resolved", because it get's the resolved value from first.

Is there any way around, without nesting anonymous functions like this:

first().then(function() {
  return second("foobar").then(function(value) {
    console.log("all resolved", value);
  });
});

I was thinking about using $q.all, but IMHO you can't specify an order for your promises.

John Slegers
  • 45,213
  • 22
  • 199
  • 169
23tux
  • 14,104
  • 15
  • 88
  • 187
  • `$timeout` already returns a promise, no need for a `$q.defer`there – Benjamin Gruenbaum Jul 23 '14 at 14:09
  • I know, it was just for demonstration purpose. In my real case, I have a http call and after that, do some processing with the data. So I do need an extra `$q.defer` – 23tux Jul 23 '14 at 14:15
  • uhh... $http also returns a promise already and you can `.then` it for the extra processing and return that... can't make a judgement about code I haven't seen but it still _sounds_ like the deferred anti pattern. You _only_ need `$q.defer` when working against a callback API when promisifying it. – Benjamin Gruenbaum Jul 23 '14 at 14:16

1 Answers1

10

Of course. First way:

first()
  .then(function() {
    return second("foobar");
  })
  .then(function(value) {
    console.log("all resolved", value);
  });

Second (much easier) way:

first()
  .then(second.bind(null, "foobar"))
  .then(function(value) {
    console.log("all resolved", value);
  });
Razem
  • 1,421
  • 11
  • 14
  • 1
    You're welcome. The important thing is you have to always remember the function can be called only by the promise. So if you need additional parameters or you need to do something with a given value, you have to wrap it or bind it and pass a plain function to the `then` call. And then the function can return another promise. – Razem Jul 23 '14 at 12:33
  • 1
    @Mawg In that case you should return an object or an array containing the desired values. – Razem Apr 16 '19 at 12:59
  • Can you show an example, for a Mawg of very little brain? ;-) – Mawg says reinstate Monica Apr 16 '19 at 13:43