Promise 执行器中的 `resolve` 和 `reject` 函数

Mar*_*tus 4 javascript

鉴于客户端程序员既定义又使用resolve传递给Promise的执行器的函数,我天真地假设我完全控制了resolve函数的签名,因此我可以定义它接受多个参数。

然而以下代码(jsFiddle)失败了:

<html>
  <script>
   const promise = new Promise(function executor(resolve, reject) {
     setTimeout(function () {
       resolve(42, true);
       }, 1000);
   });
   promise.then(function resolveCallback(answer, howCertain) {
     console.log('callback called with arguments: ('+answer+', '+howCertain+')');
     console.log('the answer is: '+answer+'. I am '+(howCertain?'very':'not very')+' certain about that');
   });
  </script>
</html>
Run Code Online (Sandbox Code Playgroud)

上面的代码实际上打印在控制台上:

callback called with arguments: (42, undefined)
the answer is: 42. I am not very certain about that
Run Code Online (Sandbox Code Playgroud)

再深入一点,我写了下面的代码(jsFiddle):

<html>
  <script>
   const promise = new Promise(function executor(resolve, reject) {
     console.log('entering executor, resolve is: ['+resolve+']'.);
     setTimeout(function () {
       console.log('about to call resolve');
       resolve(42);
       console.log('returning from resolve');       
       }, 1000);
   });
   console.log('about to call "then"');
   promise.then(function resolveCallback(answer) {
     console.log('the answer is: '+answer);
   });
  </script>
</html>
Run Code Online (Sandbox Code Playgroud)

它实际上在控制台上打印以下内容:

entering executor, resolve is: [function t() { [native code] }]
about to call "then"
about to call resolve
returning from resolve
the answer is: 42
Run Code Online (Sandbox Code Playgroud)

这证明了许多有趣的事情:

  • 在客户端程序员有机会调用 Promise 之前调用 executor then。然而,函数中的resolve参数executor不是undefined
  • resolveCallback调用中作为参数传递thenresolve函数与传递给 的函数不同executor。此外,它不会与函数resolve内部的调用同步执行(即不在同一事件循环运行中)executor

Javascript 实现这一点的唯一方法(我能想到的)是实现实际上插入了某种“代理”resolvereject函数,这些函数与客户端程序员提供的实际函数resolvereject函数异步链接。这也可以解释为什么您不能为resolvereject函数定义自己的签名:因为管道不起作用。

这种心理模型是正确的还是我遗漏了什么?

Ber*_*rgi 5

客户端程序员定义了传递给 Promise 的执行器的解析函数

不,他没有(正如您的实验所证实的那样)。执行器在new Promise创建过程中被调用。

当我调用thenpromise 时,我不传递resolve我选择的函数吗?

不,您传递了一个onResolve侦听器回调,或者实际上是一个onFulfill回调。

我的新心智模型正确吗?

是的,地表下有更多的管道。

实际上,new Promise构造函数只为您提供代理解析器函数。

一个承诺包含一个状态机。它是一个表示(一个!)异步结果的对象。因此,您可以.then()在同一个 promise 对象上多次调用,并且回调将始终传递结果。

它不是executor函数的包装器,它不会像您调用then. 执行器只被调用一次,让生产者可以访问解析器函数(状态机的输入)。调用,观察状态机输出的消费者then与此完全解耦 - 正如您所说,它们是异步链接的。

也看看这个。对于您的心智模型,是一个易于理解的Promise类实现(无保证的异步和错误处理)。