JavaScript ES6 承诺有一个标准程序,用于将几个耗时的承诺与异步任务链接在一起,这是真的吗?



我认为问题的简短版本是:如果提供给.then()的履行处理程序返回新承诺,那么这个新承诺如何"解开包装"到.then()返回的承诺? (Unwrap 似乎是 Promise 技术中使用的术语(。(如果它不是返回一个新的承诺,而只是一个"然后",它如何解开包装?

要将几个耗时的异步承诺链接在一起,例如执行此页面上描述的多个网络获取或一系列动画,我认为标准方法表述为:

在传递给.then()的履行处理程序中,创建并返回一个新的承诺p,并在传递给创建p的构造函数的执行器中,执行耗时的任务,并在完成后p解决这个新的承诺。

有时我可能会认为:这就是它的方式(如何链接耗时的承诺(,或者它是语言功能,你可以认为它是神奇的(如果它是一个语言功能(。

但是,这是通过标准程序完成的,如果履行处理程序返回新承诺,如何处理,这是真的吗?

我在下面写了一些关于如何完成的粗略草案。 用几句话来说明,它是

  1. p1是第一个承诺。
  2. then()返回一个新的承诺p2
  3. then()记得p2是什么,作为p1的内部属性。
  4. 当传递给then的履行处理程序最终被调用时(当p1解析时(,将检查返回的值。如果它是一个具有名为then的属性并且是一个函数的对象,那么这个对象被视为一个 thenable,这意味着它可以是一个真正的承诺,也可以只是一个虚拟的 thenable(我们称之为p1_New(。
  5. 立即调用以下内容:p1_New.then(() => { resolveP2() })
  6. 假设p1_New是一个真正的承诺。当我们解决p1_New时,它将解决p2p2将执行其"然后"的履行处理程序,并且一系列耗时的承诺可以继续下去。

所以这是代码的粗略草案:

let p1 = new Promise(function(resolve, reject) {
// does something that took 10 seconds
resolve(someValue);
});

在上面的代码之后,p1的状态是:

p1 = {
__internal__resolved_value: undefined,
__internal__state: "PENDING",
__internal__executor: function() {    
// this is the executor passed to the constructor Promise().
// Something is running and the resolve(v) statement probably
// will do
// this.__internal__onResolve(v)
},
__internal__onResolve: function(resolvedValue) {
if (this.__internal__then_fulfillHandler) {   // if it exists
let vFulfill = this.__internal__then_fulfillHandler(this.__internal__resolved_value);
// if the fulfillment handler returns a promise (a thenable),
// then immediately set this promise.then(fn1)
// where fn1 is to call this.__internal__resolveNewPromise()
// so as to resolve the promise newPromise that I am returning
if (vFulfill && typeof vFulfill.then === "function") { // a promise, or thenable
vFulfill.then(function() {
this.__internal__resolveNewPromise(this.__internal__resolved_value)
})
}
}
},
// in reality, the then should maintain an array of fulfillmentHandler
//   because `then` can be called multiple times
then: function(fulfillmentHandler, rejectionHandler) {
this.__internal__then_fulfillHandler = fulfillmentHandler;
// create a new promise newPromise to return in any case
let newPromise = new Promise(function(resolve, reject) {
this.__internal__resolveNewPromise = resolve;
});
// if promise already resolved, then call the onResolve 
//   to do what is supposed to be done whenever this promise resolves
if (this.__internal__state === "RESOLVED") {
this.__internal__onResolve(this.__internal__resolved_value);
}
return newPromise;
}
}

这就是当p1_New被解析时,p2被解析,传递给p2.then()的履行处理程序将继续存在的方式。

let p2 = p1.then(function() {
p1_New = new Promise(function(resolve, reject) {
// does something that took 20 seconds
resolve(someValue);
});
return p1_New;
});
p2.then(fulfillmentHandler, rejectionHandler);

但是,如果p1_New不是真正的承诺,而只是一个这样写的假thenable呢:

class Thenable {
constructor(num) {
this.num = num;
}
then(resolve, reject) {
alert(resolve); // function() { native code }
// resolve with this.num*2 after the 1 second
setTimeout(() => resolve(this.num * 2), 1000); // (**)
}
}
new Promise(resolve => resolve(1))
.then(result => {
return new Thenable(result); // (*)
})
.then(alert); // shows 2 after 1000ms

它正在then()中完成耗时的任务。这也很好:如果我们看上面的步骤5:

  1. 立即调用:p1_New.then(() => { resolveP2() })

也就是说,then立即被调用,并且传递的第一个函数能够解析p2。这样thenable执行一些耗时的任务,完成后,调用它的第一个参数(解析p2的函数(,整个序列可以像以前一样继续。

但在这种情况下,是执行耗时任务的then(),而不是执行者执行(执行器传递给新承诺的构造函数(。在某种程度上,这就像then()变成了执行者。

我现在更了解承诺,这似乎是标准方式。

无论履行处理程序返回什么:一个原始值,一个不是可然后的对象,一个像假承诺或真实承诺的可然后对象,都将被设置,以便它能够解析p,其中p是由then返回的承诺。

这是标准过程,也就是所谓的解包。 我们可以将承诺包裹和包裹很多层,当它从内部解开时,它会解开,直到它无法继续。

确实,当一个当时可以虚假的承诺,或者一个真正的承诺被返回时,它会触发这个动作发生在下面:

obj.then(resolveP)其中resolveP是可以解析p的解析函数。

该承诺如何解析p,以及thenable如何执行异步任务并使用传递给它的第一个参数作为解析函数来"解析"p

最新更新