理解 JS Promise

2024-04-15

我想更深入地了解 Promise 内部是如何工作的。 因此我有一些示例代码:

var p1 = new Promise(
  function(resolve, reject) {
    window.setTimeout(
      function() {
        resolve('res called')
      }, 2000);
  });


var p2 = new Promise(
  function(resolve, reject) {
    window.setTimeout(
      function() {
        resolve('res called')
      }, 2000);
  });


function chainPromises() {
  return p1.then(function(val) {
    console.log("p1");
    return p2.then(function(val) {
      console.log("p2");
      return val;
    });
  });
}

chainPromises().then(function(val) {
  console.log(val);
});

Here a link http://jsfiddle.net/vj08n2r1/来执行这段代码。

正如您所预测的,首先解析 p1,然后解析 p2,最后打印解析值。

但 API 参考声明如下:

“then”返回一个新的承诺,相当于您返回的值 通过 Promise.resolve 传递后的 onFulfilled/onRejected

因此,了解“then”函数到底何时执行会很有趣? 因为代码中最后的“then”链接到了 chainPromises(),所以我首先想到的是 它将在函数 chainPromises() 返回某些内容(在本例中是另一个 Promise)后执行。

如果是这种情况,最终“then”函数的“val”将是返回的承诺。 但相反,最后一个“then”会等待,直到返回的第一个“then”内的所有承诺都已得到解决。 这绝对是有道理的,因为通过这种方式,“then”函数可以被堆叠,但是 由于 API 规范,我不太明白这是如何完成的。并没有真正涵盖“then”返回的内容以及“then”函数何时执行。

或者换句话说,为什么最终的“then”函数要等到所有 Promise 在 chainPromises() 函数内得到解析,而不是像 API 文档所说的那样只等待第一个返回的对象。

我希望我能清楚地表达我的意思..:)


关于 Promise 解析

你在这里目睹的事情叫做递归的then能够分辨率。 Promises/A+规范中的promise解析过程包含以下子句:

onFulfilled或onRejected返回值x,运行Promise解析过程 [[Resolve]](promise2, x)

ES6 Promise 规范(Promise 解包)包含类似的条款。

这要求当resolve操作发生:或者在 Promise 构造函数中,通过调用Promise.resolve或者在你的情况下then链式承诺实施must如果返回值是一个承诺,则递归地解开返回值。

在实践中

这意味着如果onFulfilled (the then)返回一个值,尝试自己“解析”承诺值,从而递归地等待整个链。

这意味着以下内容:

promiseReturning().then(function(){
    alert(1);
    return foo(); // foo returns a promise
}).then(function(){
    alert(2); // will only run after the ENTIRE chain of `foo` resolved
              // if foo OR ANY PART OF THE CHAIN rejects and it is not handled this 
              // will not run
});

例如:

promiseReturning().then(function(){
    alert(1);
    return Promise.resolve().then(function(){ throw Error(); });
}).then(function(){
    alert("This will never run");
});

然后:

promiseReturning().then(function(){
    alert(1);
    return Promise.resolve().then(function(){ return delay(2000); });
}).then(function(){
    alert("This will only run after 2000 ms");
});

这是不是一个好主意?

这是承诺规范过程中备受争议的话题,讨论了第二个不表现出这种行为的链方法,但决定反对(在 Chrome 中仍然可用,但很快就会被删除)。您可以阅读整个辩论的内容在此讨论主题中 https://esdiscuss.org/topic/promise-cast-and-promise-resolve. 这种行为是出于务实的原因这样您就不必手动执行此操作。

在其他语言中

值得一提的是,其他语言并没有这样做,Scala 中的 future 或 C# 中的任务都没有这个属性。例如在 C# 中你必须调用Task.Unwrap任务以等待其链解决。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

理解 JS Promise 的相关文章