从一行 new Promise 看懂 JavaScript 异步核心
看这段代码:
console.log(1);
const p = new Promise((resolve, reject) => {
console.log(3); // 同步执行
fs.readFile('./a.txt', (err, data) => {
if (err) {
reject(err);
return;
}
resolve(data.toString());
});
});
p.then((data) => {
console.log(data);
console.log(4);
}).catch((err) => {
console.log(err, '/////');
console.log(5);
});
console.log(2);
输出顺序是:1 → 3 → 2 → 文件内容 → 4(或错误 → 5)
为什么?关键在理解 Promise 的四个核心机制:
1. Executor 立即同步执行
new Promise() 接收的函数叫 executor,它在创建 Promise 时立刻同步运行。
所以 console.log(3) 在 console.log(2) 之前输出。
但其中的 fs.readFile 是异步 I/O,会交给 Node.js 底层线程池处理,不阻塞主线程。
2. 状态只能决议一次,且不可逆
- 调用
resolve(value)→ Promise 变为 fulfilled,值为value。 - 调用
reject(error)→ Promise 变为 rejected,原因为error。 - 无论哪种,只能发生一次。后续调用无效。
这意味着:一个 Promise 只有一个结果——成功或失败,二者必居其一,且终局已定。
3. .then() / .catch() 是微任务
当 Promise 状态确定后,.then() 或 .catch() 中的回调会被放入微任务队列,在当前同步代码执行完后立即执行。
因此 console.log(2) 先于文件内容输出。
4. .then() 必须传函数,否则值穿透
如果 .then() 的参数不是函数(比如数字、字符串、Promise 对象等),JavaScript 会将其忽略,并将上一个值原样透传给下一个 .then():
Promise.resolve(1)
.then(2) // 非函数 → 忽略
.then(Promise.resolve(3)) // 非函数 → 忽略
.then(console.log); // 输出:1
✅ 规则:只有函数能消费值;非函数 = 跳过,值不变传递。
总结
executor同步执行,启动异步任务;- Promise 状态一锤定音,不可更改;
- 成功走
.then(),失败走.catch(),错误可冒泡; - 非函数参数触发值穿透;
- 所有回调通过微任务调度,保证执行顺序。