JS ES6 Promise Chaining

2019-01-26 11:21发布

问题:

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);
});

回答1:

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);
});


回答2:

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);
});


回答3:

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;
});


回答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:

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.



回答5:

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);
    }