Promise的执行者内部的`resolve`和`reject`函数

时间:2018-05-18 14:28:02

标签: javascript

鉴于客户端程序员都定义并使用传递给Promise的执行者的resolve函数,我天真地认为我完全控制了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>

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

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

深入挖掘,我编写了以下代码(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>

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

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

这展示了许多有趣的事情:

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

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

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

1 个答案:

答案 0 :(得分:4)

  

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

不,他没有(正如你的实验证实的那样)。在new Promise创建期间调用执行程序。

  

当我在承诺上致电then时,我是否通过了我选择的resolve功能?

不,您通过了onResolve侦听器回调或actually an onFulfill回调。

  

我的新心理模型是否正确?

是的,表面下方有更多的管道。

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

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

它不是executor函数的包装器,它不会像调用then那样经常调用执行程序。执行程序只调用一次,以使 producer 访问解析程序函数(状态机的输入)。调用then,观察状态机输出的使用者与此完全分离 - 正如您所说,它们是异步链接。

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