鉴于客户端程序员定义并使用传递给 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
这展示了许多有趣的事情:
- 在客户端程序员有机会调用 Promise
then
之前调用执行器。然而,executor
函数中的resolve
参数并不undefined
。 - 在对
then
的调用中作为参数传递的resolveCallback
函数与传递给executor
的resolve
函数不同。此外,它不会与executor
函数中的resolve
调用同步执行(即不在同一个事件循环运行中(。
Javascript实现这一目标的唯一方法(我能想到的(是实现实际上是插入某种"代理"resolve
和reject
函数,这些函数异步链接到客户端程序员提供的实际resolve
和reject
函数。这也解释了为什么你不能为resolve
和reject
函数定义自己的签名:因为管道不起作用。
这个心智模型是正确的还是我错过了什么?
客户端程序员定义传递给 Promise 执行者的 resolve 函数
不,他没有(正如你的实验所证实的那样(。在创建new Promise
期间调用执行器。
当我打电话给
then
承诺时,我不是传递我选择的resolve
函数吗?
否,您传递onResolve
侦听器回调,或者实际上是onFulfill
回调。
我的新心智模型正确吗?
是的,地表以下有更多的管道。
实际上,new Promise
构造函数只为您提供代理解析器函数。
承诺包含状态机。它是一个表示(一个!(异步结果的对象。因此,您可以在同一个 promise 对象上多次调用.then()
,并且回调将始终传递结果。
它不是executor
函数的包装器,它不像您调用then
那样频繁地调用执行器。执行器只调用一次,以使生产者能够访问解析器函数(状态机的输入(。调用then
的消费者,观察状态机的输出,与此完全解耦 - 正如您所说,它们是异步链接的。
也看看这个。对于您的心智模型,这是Promise
类的易于理解的实现(没有保证异步和错误处理(。