javascript的async和await是什么_怎样简化异步代码编写?

async 和 await 是基于 Promise 的异步语法糖:async 函数返回 Promise,await 暂停执行直至 Promise 完成;需在 async 函数内使用,配合 try/catch 处理错误,支持自动包装非 Promise 值,但须合理设计串行/并行逻辑。

async 和 await 是什么?

它们是 JavaScript 中处理异步操作的语法糖,本质仍是基于 Promise,但让异步代码写起来像同步代码一样线性、易读。async 用于声明一个函数会返回 Promiseawait 只能在 async 函数内部使用,用来“暂停”执行直到右侧的 Promise 被 resolve 或 reject。

怎么用 await 等待 fetch 请求?

直接在 async 函数里用 await fetch(...) 获取响应,再用 await response.json() 解析数据。注意:两次 await 都可能抛错,必须捕获。

async function getUser() {
  try {
    const response = await fetch('/api/user');
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    const data = await response.json();
    return data;
  } catch (err) {
    console.error('获取用户失败:', err.message);
  }
}
  • fetch() 本身只在网络失败时 reject,HTTP 404/500 不会触发 catch,得手动检查 response.ok
  • 不能在顶层(非函数作用域)直接写 await,否则报错 Uncaught SyntaxError: await is only valid in async function
  • 如果只是想等多个请求并行,别用 await Promise.all([...]) 套两层,直接 await Promise.all([fetch(...), fetch(...)])

为什么 await 后面不是 Promise 也能用?

await 会自动把非 Promise 值包装成已 resolve 的 Promise。比如 await 42 等价于 await Promise.resolve(42),所以能安全地混用同步值和异步逻辑。

  • 这让你可以统一用 await 处理缓存命中(返回普通对象)和缓存未命中(返回 Promise
  • 但别滥用:对纯同步值加 await 没实际意义,还可能掩盖本该同步执行的逻辑意图
  • 类型工具(如 TypeScript)不会自动推导 await 42 的类型为 number,需显式标注或依赖上下文

常见错误:忘记处理 rejected Promise

没加 try/catch,或只捕获了第一层 await,后续链式调用仍可能出错。尤其在连续 await 多个异步操作时,任一环节 reject 都会导致整个函数中断。

async function badExample() {
  const user = await fetchUser(); // 如果这里 reject,下面不会执行
  const posts = await fetchPosts(user.id); // 这行根本跑不到
  return { user, posts };
}
  • 每个 await 行为都可能失败,建议按业务粒度包裹 try/catch,而不是整个函数包一层
  • 避免在循环中无节制 await:比如 for (const id of ids) await fetch(`/item/${id}`) 是串行,性能差;改用 Promise.all(ids.map(id => fetch(...)))
  • async 函数返回值总是 Promise,即使你 return 123,调用方也必须用 .then() 或外层 await 接收
实际写多了就会发现,最难的不是语法,而是判断哪些地方该串行 await、哪些该并行 Promise.all、哪些该提前 reject —— 这些取决于接口语义和错误恢复策略,不是加个 async 就万事大吉。