javascript - Promise 执行器中的 `resolve` 和 `reject` 函数
问题描述
鉴于客户端程序员既定义并使用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>
上面的代码实际上打印在控制台上:
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
promise 之前调用 executor。然而,函数resolve
中的参数executor
不是undefined
。 - 在
resolveCallback
调用中作为参数传递then
的resolve
函数与传递给executor
.resolve
此外,它不会与函数内部的调用同步执行(即不在同一个事件循环中运行)executor
。
Javascript 实现这一点的唯一方法(我能想到的)是该实现实际上是插入某种“代理”resolve
和reject
函数,这些“代理”和函数异步链接到客户端程序员提供的实际函数resolve
和函数。reject
这也可以解释为什么您不能为resolve
andreject
函数定义自己的签名:因为管道不起作用。
这个心智模型是正确的还是我错过了什么?
解决方案
客户端程序员定义传递给 Promise 执行者的解析函数
不,他没有(正如你的实验所证实的那样)。new Promise
executor 在创建期间被调用。
当我
then
兑现承诺时,我不传递resolve
我选择的功能吗?
不,您传递了一个onResolve
侦听器回调,或者实际上是一个onFulfill
回调。
我的新心智模型正确吗?
是的,地表以下有更多的管道。
实际上,new Promise
构造函数只是为您提供代理解析器函数。
Promise 包含一个状态机。它是一个表示(一个!)异步结果的对象。因此,您可以.then()
在同一个 Promise 对象上多次调用,并且回调将始终传递结果。
它不是函数的包装器executor
,它不像你调用的那样频繁地调用执行器then
。执行器只被调用一次,让生产者可以访问解析器函数(状态机的输入)。调用的消费者then
,观察状态机的输出,与此完全解耦——正如你所说,它们是异步链接的。
推荐阅读
- swift - 如何从 NIB 创建自定义 NSTableCellView?
- phantomjs - 使用 PhantomJS 访问 URL 时出现 403 Forbidden
- postgresql - 如何将oracle的流水线功能迁移到PostgreSQL中
- android - 使用 TelecomManager 和我们的自定义协议
- java - 处理异常时保存不起作用
- widget - 自定义 Jira 嵌入式小部件
- html - 模式在除 Safari 之外的所有浏览器中打开
- azure-ad-b2c - Azure B2C - 安全问题
- python - 函数参数列表中的元组
- android - Android 应用程序在通知点击时启动缓慢