本文由一缘原创整理,内容涵盖 Promise 的本质、常见用法、链式调用、错误处理、并发控制、常见陷阱与最佳实践,配合丰富代码和输出,适合所有前端开发者。

彻底讲通 JavaScript 的 Promise

Promise 是现代 JavaScript 异步编程的基石。理解 Promise,不仅能写出更优雅的异步代码,还能为 async/await 打下坚实基础。


1. Promise 是什么?

Promise 是一个代表未来某个异步操作结果的对象,有三种状态:

  • pending(进行中)
  • fulfilled(已成功)
  • rejected(已失败)

一旦状态变为 fulfilled 或 rejected,就不可再变。


2. Promise 的基本用法

const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功!');
  }, 1000);
});

p.then(result => {
  console.log(result);
});

输出:

(1秒后) 成功!

3. Promise 的链式调用

then() 返回的也是一个 Promise,可以链式调用:

Promise.resolve(1)
  .then(x => x + 1)
  .then(x => x * 2)
  .then(x => {
    console.log(x);
    return x;
  });

输出:

4

4. 捕获异常与 catch

Promise.reject('出错了')
  .then(res => {
    // 不会执行
  })
  .catch(err => {
    console.log('捕获到错误:', err);
  });

输出:

捕获到错误: 出错了

5. finally 的用法

finally 无论 Promise 成功还是失败都会执行:

Promise.resolve('ok')
  .finally(() => {
    console.log('无论如何都会执行');
  })
  .then(res => console.log(res));

输出:

无论如何都会执行
ok

6. Promise.all 与 Promise.race

Promise.all

所有 Promise 都成功才 resolve,有一个失败就 reject:

Promise.all([
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.resolve(3)
]).then(res => console.log(res));

输出:

[1, 2, 3]

Promise.race

谁先完成就返回谁的结果:

Promise.race([
  new Promise(res => setTimeout(() => res('A'), 100)),
  new Promise(res => setTimeout(() => res('B'), 50))
]).then(res => console.log(res));

输出:

B

7. Promise.allSettled 与 Promise.any

Promise.allSettled

无论成功失败,全部执行完后返回每个 Promise 的结果状态:

Promise.allSettled([
  Promise.resolve('ok'),
  Promise.reject('fail')
]).then(res => console.log(res));

输出:

[
  { status: 'fulfilled', value: 'ok' },
  { status: 'rejected', reason: 'fail' }
]

Promise.any

只要有一个成功就 resolve,全失败才 reject:

Promise.any([
  Promise.reject('fail'),
  Promise.resolve('ok')
]).then(res => console.log(res));

输出:

ok

8. Promise 的常见陷阱

then/catch 没有返回新 Promise

Promise.resolve(1)
  .then(x => {
    // 忘记 return
    x + 1;
  })
  .then(x => console.log(x));

输出:

undefined

then/catch 里抛出异常

Promise.resolve()
  .then(() => {
    throw new Error('出错了');
  })
  .catch(e => console.log(e.message));

输出:

出错了

9. Promise 的最佳实践

  • 总是返回 Promise,不要混用回调和 Promise。
  • 链式调用时记得 return,否则下一个 then 得到 undefined。
  • 错误要 catch,否则会被吞掉。
  • 避免 Promise 嵌套,用链式写法更优雅。
  • async/await 是 Promise 的语法糖,理解 Promise 是写好 async/await 的基础。

10. 手写一个最简 Promise

理解原理,手写一个极简 Promise:

class MyPromise {
  constructor(fn) {
    this.cbs = [];
    fn(this.resolve.bind(this));
  }
  resolve(val) {
    setTimeout(() => {
      this.cbs.forEach(cb => cb(val));
    });
  }
  then(cb) {
    this.cbs.push(cb);
    return this;
  }
}

new MyPromise(res => res(42)).then(x => console.log(x));

输出:

42

11. async/await 与 Promise

async 函数返回的就是 Promise,可以用 await 等待 Promise 结果:

function delay(ms) {
  return new Promise(res => setTimeout(res, ms));
}

async function main() {
  await delay(100);
  console.log('done');
}
main();

输出:

done

结语

Promise 是 JS 异步的核心,理解它能让你写出更健壮、优雅的前端代码。欢迎留言交流更多 Promise 相关问题!