鉴于客户端程序员都定义并使用传递给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解决此问题的唯一方法(我能想到的)是实现实际上是插入某种与异步链接的“代理”executor
和resolve
函数客户端程序员提供的实际reject
和resolve
函数。这也可以解释为什么你不能为reject
和resolve
函数定义自己的签名:因为管道不起作用。
这种心理模型是正确的还是我错过了什么?
答案 0 :(得分:4)
客户端程序员定义传递给Promise执行者的解析函数
不,他没有(正如你的实验证实的那样)。在new Promise
创建期间调用执行程序。
当我在承诺上致电
then
时,我是否通过了我选择的resolve
功能?
不,您通过了onResolve
侦听器回调或actually an onFulfill
回调。
我的新心理模型是否正确?
是的,表面下方有更多的管道。
实际上,new Promise
构造函数只为您提供代理解析器函数。
承诺包含状态机。它是一个表示(一个!)异步结果的对象。因此,您可以在同一个promise对象上多次调用.then()
,并且回调将始终传递结果。
它不是executor
函数的包装器,它不会像调用then
那样经常调用执行程序。执行程序只调用一次,以使 producer 访问解析程序函数(状态机的输入)。调用then
,观察状态机输出的使用者与此完全分离 - 正如您所说,它们是异步链接。