JS ES6 Promise Chaining
Asked Answered
A

5

12

I'm trying to learn how to use promises, but am having trouble comprehending the chaining. I assume that with this code, both promises will run. Then when I call test.then() it should know that test has resolved and pass the resolve data to then().

Once that function finishes, it goes onto the next then(), repeating the same process with the test2 promise.

However, I can only get it to print out the first promise results, not the second. Any ideas what is missing here?

var test = new Promise(function(resolve, reject){
    resolve('done1');
});

var test2 = new Promise(function(resolve, reject){
    resolve('done2');
});

test
.then(function(data) {
    console.log(data);
})
.then(test2)
.then(function(data) {
    console.log(data);
});
Amalita answered 29/2, 2016 at 22:33 Comment(2)
You must not pass a promise to then, but a callback function.Heteromerous
In general, you're going to be creating functions that return promises based on some specific need or input, not just assigning a "new" Promise to a variable. That way of creating promises is almost never necessary unless you are adapting some other async feature to Promises. So a more legit dummy case might be: var test2 = x => new Promise(function(res, rej){ resolve(x); }); because at least there you're modeling a function that does something with data. And something like .then(test2) can actually work/be meaningful.Farland
O
20

Your first .then call is returning undefined, whereas any subsequent .then is expecting a returned promise. So you'd need to change your code to:

var test = new Promise(function(resolve, reject){
    resolve('done1');
});

var test2 = new Promise(function(resolve, reject){
    resolve('done2');
});

test
.then(function(data) {
    console.log(data);
    return test2;
})

.then(resultOfTest2 => doSomething)
.then(function(data) {
console.log(data);
});
Omniscience answered 29/2, 2016 at 22:36 Comment(1)
Thank you very much. I feel like a fool for missing this but hopefully it helps other people with the same problem.Amalita
J
4

You need to return next promise from the then callback:

test.then(function(data) {
    console.log(data);
    return test2;
}).then(function(data) {
    console.log(data);
});
Joke answered 29/2, 2016 at 22:36 Comment(0)
S
4

Summary:

The basic concept of promise chaining with promises is that every then / catch method on a fulfilled promise returns another promise. It works in the following manner:

  • When a promise is resolved the callback passed in the then method is called. The then method wraps the value which is returned in its callback in a resolved promise and returns this resolved promise.
  • When a promise is rejected the callback passed in the catch method is called. The catch method wraps the value which is returned in its callback in a rejected promise and returns this rejected promise.

Example:

Before fully understanding the concept of chaining multiple then methods it is important to know what exactly the return values of then and catch are. Take the following example:

let prom1 = new Promise((res, rej) => {
  res('res');
});

const resolvedProm1 = prom1.then((val) => {return val});
// setTimeout needed for the promise to actually be resolved
setTimeout(() => console.log(resolvedProm1));

let prom2 = new Promise((res, rej) => {
  rej('rej');
});

const resolvedProm2 = prom2.catch((err) => {throw err});
// setTimeout needed for the promise to actually be rejected
setTimeout(() => console.log(resolvedProm2));

We can observe the status of the promises in the chrome devtools:

promises javascript

What basically happens is that in a then or catch callback is the following:

  • Any value returned in a then or catch callback is wrapped in Promise.resolve() and a new resolved promise is returned.
  • Any error thrown in a then or catch callback is wrapped in Promise.reject() and a new rejected promise is returned.

Because we are getting returned a rejected or resolved promise object we can repeat the cycle and call the then or catch method on it again. For example:

const prom = new Promise((res, rej) => {
  if (Math.random() > 0.5) {
    res('success');
  } else {
    rej('error');
  }
});

prom.then((val) => {
  return val;
}).then((val) => {
  return val
}).then((val) => {
  console.log(val)
}).catch((err) => {
  console.log('err');
})

This calling of then and catch methods which are executed in their respective order is called promise chaining. It is a very useful technique to make working with asynchronous code easier, especially if multiple asynchronous operations need to be performed which are dependend on each others data.

Shirelyshirey answered 29/9, 2018 at 13:40 Comment(0)
S
2

you need to return the other promise(test2) in the first promise (test1) to allow for chaining:

  var test = new Promise(function(resolve, reject){
    resolve('done1');
});

var test2 = new Promise(function(resolve, reject){
    resolve('done2');
});

test
.then(function(data) {
  console.log(data);
  return test2;
});
Sillabub answered 29/2, 2016 at 22:41 Comment(0)
C
0

You may also want to try -

    let test = new Promise(function(resolve, reject){
        resolve('done1');
    });

    let test2 = new Promise(function(resolve, reject){
        resolve('done2');
    });

    try {
        let logOne = test();
        let logTwo = test2();
        console.log(logOne);
        console.log(logTwo);
    } catch(error) {
        console.error(error);
    }

In this way, you can also properly handle any promise dependencies. For example if test one relied on test two's data your could -

try {
        let logOne = test();
        let logTwo = test2(logOne);
        console.log(logOne);
        console.log(logTwo);
    } catch(error) {
        console.error(error);
    }
Charactery answered 3/8, 2017 at 20:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.