为什么 Promise 构造函数需要一个在完成时调用 'resolve' 的函数,但 'then' 不需要 - 它 returns 是一个值?

Why does the Promise constructor require a function that calls 'resolve' when complete, but 'then' does not - it returns a value instead?

当我投入研究 Promises 时,我的理解停滞在以下我没有发现讨论的问题上(我发现的只是 Promise 构造函数的具体讨论,以及 Promise 'then' 函数 - 但不是比较他们设计模式的讨论)。


1。 Promise构造函数

From the MDN documentation我们使用了 Promise 构造函数(添加了我的评论):

new Promise(function(resolve, reject) { ... }); // <-- Call this Stage 1

Function object with two arguments resolve and reject. The first argument fulfills the promise, the second argument rejects it. We can call these functions, once our operation is completed.


2。 then函数

继续 then 函数 可以在 Promise 对象上调用(return 是一个新的 Promise 对象),我们有 the following function signature as described by the documentation(添加了我的评论):

p.then(onFulfilled, onRejected);

Chaining

Because the then method returns a Promise, you can easily chain then calls.

var p2 = new Promise(function(resolve, reject) {
  resolve(1); // <-- Stage 1 again
});

p2.then(function(value) {
  console.log(value); // 1
  return value + 1; // <-- Call this Stage 2
}).then(function(value) {
  console.log(value); // 2
});

我的问题

从上面的代码片段中,我似乎很清楚在阶段 1 中传递给 resolve 函数的 值(在第二次出现 resolve - 在 (2) 之下,上面) 被传递到下一阶段(同一代码片段中的第一个 then 函数)。 第一阶段没有return值。但是,通过的是第二阶段的return值之后进入下一阶段(第二个 then 函数)。

创建 Promise 的设计模式与在现有承诺上使用 then 函数(这也是 return Promise), 只是一个历史侥幸(一个需要调用回调但 return 什么都没有,另一个 return 是一个值但不调用回调)?

或者我是否遗漏了 Promise 构造函数使用与 then 函数不同的设计模式的根本原因?

Promise构造函数和then方法之间没有对应关系,因为它们是两个独立的东西,为不同的目的而设计。

Promise构造函数仅用于promisifying1异步函数。事实上,正如你所说,它是建立在 调用 resolve/reject 回调到 异步发送 值的基础上,并且有在这种情况下没有 return 值。

Promise 构造函数本身确实采用此 "resolver" 回调(它同步传递 resolvereject)实际上是对旧 延迟模式,并且与 then 回调没有预期的相似性

var p = new Promise(function(res, rej) {    |    var def = Promise.Deferred();
    setTimeout(res, 100);                   |    setTimeout(def.resolve, 100);
});                                         |    var p = def.promise;

相比之下,then 回调是经典的异步回调,您可以从中 additional feature return。它们被异步调用接收值。

p.then(function(val) { … });

总结差异:

  • Promise是一个构造函数,而then是一个方法
  • Promise需要一个回调,而then最多需要两个
  • Promise 同步调用其回调,而 then 异步调用其回调
  • Promise 总是调用它的回调,
    then 可能不会调用其回调(如果承诺不是 fulfilled/rejected)
  • Promise 将功能传递给 resolve/reject 对回调的承诺,
    then 传递调用它的承诺的结果值/拒绝原因
  • Promise 调用其回调以执行副作用(调用 reject/resolve),
    then 为其结果值调用其回调(用于链接)

是的,两者都有 return 承诺,尽管它们与许多其他功能(Promise.resolvePromise.rejectfetch、...)共享该特性。事实上,所有这些都基于 Promise 构造函数提供的相同的承诺构造和 resolve/reject 功能,尽管这不是它们的主要目的。 then 基本上提供了将 onFulfilled/onRejected 回调附加到现有承诺的能力,这与 Promise 构造函数相当不同。

两者都使用回调只是巧合 - 不是历史侥幸,而是语言特性的共同适应。

1:理想情况下,您永远不需要这个,因为所有本机异步 API return promises

promise 构造函数执行器函数的全部意义在于将 resolve 和 reject 函数传播到不使用 promise 的代码,包装它并将其转换为使用 promise。如果您只想将其限制为同步函数,那么是的,可以使用函数中的 return 值来代替,但这会很愚蠢,因为有用的部分是将解析器和拒绝函数传播到代码中实际上稍后运行(在 return 之后),例如传递给一些异步 API.

的回调

非常好,对我帮助很大。这个答案是对他的补充。为了可视化 Promise() 构造函数和 then() 方法之间的关系,我创建了这张图。我希望它能帮助别人......也许甚至是我,几个月后。

这里的主要思想是传递给 Promise() 构造函数的 "executor" 函数启动任务,这些任务将 设置承诺的状态 ;而您传递给 then() 的处理程序将 对承诺的状态 做出反应。

(代码示例改编自 Jake Archibald's classic tutorial。)

这是对事物运作方式的高度简化视图,省略了许多重要细节。但我认为,如果一个人能够很好地掌握预期目的的概况,将有助于避免在进入细节时产生混淆。

几个选定的细节

立即调用执行器

一个重要的细节是传递给 Promise() 构造函数的执行函数 立即被调用 (在构造函数 returns 承诺之前);而传递给 then() 方法的处理函数直到 以后 (如果有的话)才会被调用。

Bergi 提到了这一点,但我想在不使用术语 a/synchronously 的情况下重申它,如果您不仔细阅读可能会混淆:函数 调用 [= 之间的区别66=] 异步与 被异步调用 很容易在通信中被掩盖。

resolve() 不是 onFulfill()

我想强调的另一个细节是 resolve()reject() 回调传递给 Promise() 构造函数的执行函数 resolve()reject() =56=]不是后来传递给then()方法的回调。回想起来这似乎很明显,但明显的联系让我原地打转了太久。肯定有联系,但它是松散的、动态的。

相反,resolve()reject() 回调函数 由 "system" 提供,并由Promise 创建承诺时的构造函数。当 resolve() 函数被调用时,系统代码会被执行,这可能会改变承诺的状态并最终导致 onFulfilled() 回调被异步调用。不要将调用 resolve() 视为调用 onFulfill()!

的紧密包装

受前面答案的启发(我将解决让我最困惑的部分):

Promise 构造函数中的 resolvereject 参数不是您定义的函数。将它们视为您可以嵌入到异步操作代码中的钩子(通常您 resolve 成功响应和 reject 失败原因),以便 javascript 有办法最终标记Promise 是 Fulfilled 还是 Rejected,具体取决于您的异步操作的结果;一旦发生这种情况,您在 then(fun1, fun2) 中定义的适当函数将被触发以使用 Promise(fun1(success_response)fun2(failure_reason),具体取决于 Promise 是否为 Fulfilled/Rejected)。由于 fun1fun2 是普通的旧 javascript 函数(它们恰好将异步操作的未来结果作为参数),它们 return 值(可以是 undefined 如果你没有明确说明 return).

另请参阅 Mozilla 的精彩文章:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

下面是Promise的执行流程。

var p = new Promise((resolve, reject) =>{
console.log("1");
resolve("OK");
});


//The above code creates a promise and execustion starts immediately.
//it happens aynchronously. So the execution will not be blocked. 
//Promise exustion will not wait for 'then' call on promise

console.log("2");
//The above line displays 2 on the console. 

p.then((result)=>{
console.log("3");
console.log(result);
});

//The above code shoud not block execution. So it may print 4 first 
// then 3
console.log("4");