JS ES6 承诺链接

JS ES6 Promise Chaining

我正在尝试学习如何使用 promises,但在理解链接时遇到问题。我假设使用这段代码,两个承诺都将 运行。然后当我调用 test.then() 它应该知道测试已经解决并将解决数据传递给 then()。

一旦该函数完成,它就会进入下一个 then(),用 test2 promise 重复相同的过程。

但是,我只能让它打印出第一个承诺结果,而不是第二个。知道这里缺少什么吗?

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

您需要 return 来自 then 回调的下一个承诺:

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

您的第一个 .then 调用正在返回 undefined,而任何后续 .then 都期望返回承诺。因此,您需要将代码更改为:

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

您需要 return 第一个承诺 (test1) 中的另一个承诺 (test2) 以允许链接:

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

您可能还想尝试 -

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

这样,你也可以妥善处理任何promise依赖。例如,如果测试一依赖于测试二的数据,您可以 -

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

总结:

承诺与承诺链接的基本概念是每个 then / catch 方法实现的承诺 return 是另一个承诺。它以下列方式工作:

  • 当一个 promise 被解析时,调用 then 方法中传递的回调。 then 方法将在其回调中 returned 的值包装在已解决的承诺中,并 return 将此已解决的承诺
  • 当承诺被拒绝时,调用 catch 方法中传递的回调。 catch 方法将在其回调中 returned 的值包装在一个被拒绝的承诺中,并且 return 是这个被拒绝的承诺

示例:

在完全理解链接多个 then 方法的概念之前,了解 thencatch 的 return 值到底是什么很重要。举个例子:

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

我们可以在 chrome devtools 中观察 promise 的状态:

基本上发生的是 thencatch 回调如下:

  • thencatch 回调中 return 的任何值都包含在 Promise.resolve() 和新的 resolved 承诺中是 returned.
  • thencatch 回调中抛出的任何错误都包含在 Promise.reject() 中,新的 rejected 承诺是 returned.

因为我们正在 returned 拒绝或解决的承诺对象,我们可以重复循环并再次调用 thencatch 方法。例如:

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

这种按各自顺序执行的thencatch方法的调用称为promise chaining。这是一种非常有用的技术,可以使使用异步代码更容易,尤其是在需要执行多个相互依赖于其他数据的异步操作时。