Promise回调eager求值的规范定义与实现细节咨询
结论
这个行为是ECMAScript规范明确定义的标准行为,不是JavaScript引擎的私有实现细节。
具体逻辑说明
Promise构造函数的执行规则从标准层面就明确了:
- 传入构造函数的executor回调(也就是示例中
(resolve) => { resolve() }这段),会被同步立即执行,执行时机在构造函数返回Promise实例之前。 - 调用executor时传入的
resolve、reject方法,本质是绑定了当前Promise内部状态的函数,一旦被调用,会立刻同步修改Promise的内部状态:- 调用
resolve(value)会把状态从pending改为fulfilled,内部结果值设为传入的value - 调用
reject(reason)会把状态从pending改为rejected,内部拒因设为传入的reason
- 调用
给出的示例代码执行流程完全符合规范:
var promise = new Promise((resolve) => { resolve() });
- 构造函数首先创建一个初始状态为
pending的内部Promise对象 - 立刻同步执行传入的executor,将内置的
resolve方法作为参数传入 - executor里同步调用了
resolve(),Promise内部状态立刻从pending变更为fulfilled - executor执行完成后,构造函数才会把已经是fulfilled状态的Promise实例返回,赋值给
promise变量 - 后续执行
console.log(promise)时,观测到fulfilled状态是必然结果。
常见认知误区澄清
预期中"存在pending状态时间窗口"的场景,只有在resolve/reject被放到异步任务中触发时才会出现,比如:
// 这个promise才会有1秒的pending窗口 var promise = new Promise((resolve) => { setTimeout(() => resolve(), 1000); }); console.log(promise); // 此时打印的是pending状态的Promise
需要额外注意:Promise规范唯一强制要求异步执行的部分,是then/catch/finally注册的回调函数——这些回调必须被放入微任务队列异步执行,哪怕Promise已经是落定状态,绑定的回调也绝对不会同步触发,比如:
Promise.resolve().then(() => console.log("then回调执行")); console.log("同步代码先执行"); // 固定输出顺序: // 同步代码先执行 // then回调执行
这个异步调度规则和"executor同步执行、resolve同步修改状态"的规则并不冲突。
内容的提问来源于stack exchange,提问作者Vito De Tullio
相关产品推荐
相关产品推荐

