javascript怎样处理异步操作_promise如何使用【教程】

10次阅读

promise构造函数必须传入执行器函数,它立即执行并接收resolve和reject参数;.then()可处理成功与失败,但推荐用.catch()统一捕获异常;async/await是Promise语法糖,需在async函数中使用;Promise.all全成功才resolve,Promise.race以最先settled者为准。

javascript怎样处理异步操作_promise如何使用【教程】

Promise 构造函数里必须传执行器函数

Promise 不是直接调用就能跑起来的,它需要一个「执行器函数」(executor),也就是 new Promise(fn) 中那个 fn。这个函数会立即执行,且接收两个参数:resolvereject —— 它们是 Promise 内部提供的回调,不是你随便定义的变量。

常见错误是漏写执行器、或把异步逻辑写在 new Promise 外面:

const p = new Promise(); // ❌ 报错:executor is required
const p = new Promise(() => {   setTimeout(() => resolve('done'), 100); // ❌ resolve is not defined });

正确写法:

const p = new Promise((resolve, reject) => {   setTimeout(() => resolve('done'), 100); });
  • resolve 触发 fulfilled 状态,值会传给后续 .then()
  • reject 触发 rejected 状态,等价于抛出异常,会被 .catch().then(NULL, fn) 捕获
  • 执行器中若抛出未捕获错误,Promise 自动进入 rejected 状态

.then() 的两个参数分别处理成功和失败

.then() 接收两个可选函数:第一个处理 fulfilled 值,第二个处理 rejected 原因。很多人只写第一个,结果错误被吞掉:

立即学习Java免费学习笔记(深入)”;

p.then(   value => console.log(value),   reason => console.error(reason) // ✅ 显式处理错误 );

但更推荐统一用 .catch(),因为:

  • .catch(fn) 等价于 .then(null, fn),语义更清晰
  • 它能捕获前面任意 .then() 中抛出的错误(链式调用中的异常冒泡)
  • 避免在每个 .then() 都重复写错误处理逻辑

注意:.catch() 只捕获 Promise rejection,不捕获同步 throw(除非 throw 发生在 Promise 执行器或 .then() 回调里)。

async/await 是 Promise 语法糖,不是替代品

async 函数返回的是 Promise 对象await 后面的表达式必须是 Promise(或可转为 Promise 的值)。它只是让 Promise 链写起来像同步代码,底层没变。

常见误区:

  • await 不能用在普通函数里,必须包裹在 async 函数中
  • await 后面如果是普通值(如 await 42),会自动包装成 Promise.resolve(42)
  • 并发执行多个 Promise,别写成 await p1; await p2;(串行),改用 await Promise.all([p1, p2])

错误示例:

function fetchUser() {   return await fetch('/user'); // ❌ SyntaxError:await only valid in async function }

正确写法:

async function fetchUser() {   const res = await fetch('/user');   return res.json(); }

Promise.all 和 Promise.race 的行为差异很关键

两者都接受 Promise 数组,但失败策略完全不同:

  • Promise.all([p1, p2, p3]):全部 fulfilled 才 resolve;只要一个 rejected,就立刻 reject(带第一个失败的 reason)
  • Promise.race([p1, p2, p3]):哪个 Promise 先 settle(fulfill 或 reject),就以它的结果为准

典型误用场景:用 Promise.race 做超时控制时,忘了它也会把先发生的 rejection 当作 race 结果。如果请求本身很快失败,超时逻辑就失效了。

安全的超时写法要确保 timeout Promise 只可能 fulfill,不能 reject:

const timeout = (ms, promise) =>   Promise.race([     promise,     new Promise((_, reject) =>       setTimeout(() => reject(new Error('timeout')), ms)     )   ]);

真正容易被忽略的是:Promise 链一旦进入 rejected 状态,又没被 .catch() 拦住,就会变成 unhandled rejection —— 浏览器控制台报黄警告,node.js 可能直接退出进程。别依赖全局 unhandledrejection 事件兜底,该 catch 的地方必须显式处理。

text=ZqhQzanResources