Promise 一

70 阅读1分钟

从一行 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(),错误可冒泡;
  • 非函数参数触发值穿透
  • 所有回调通过微任务调度,保证执行顺序。