async和await是如何革新javascript异步处理的【教程】

11次阅读

async/await是promise语法糖,不改变事件循环机制;await仅暂停当前async函数执行,不阻塞线程;必须在async函数内使用;返回值总是Promise;错误需用try/catch捕获;并发需用Promise.all等主动实现。

async和await是如何革新javascript异步处理的【教程】

async/await 本质上是 Promise 的语法糖,不是新异步机制

它没有改变 javaScript 异步的底层模型(仍是基于微任务、事件循环),只是让基于 Promise 的异步流程写起来更像同步代码。你写 await fetch('/api'),实际等价于 fetch('/api').then(...),只是引擎自动帮你展开和错误捕获了。

常见误解是“用了 await 就能阻塞线程”——完全错误。await 只是暂停当前 async 函数的执行,把控制权交还给事件循环,不会阻塞主线程或其它任务。

await 必须在 async 函数内使用,否则 SyntaxError

直接写 await Promise.resolve(42) 在顶层或普通函数里会报 SyntaxError: await is only valid in async function。这是硬性语法规则,不是运行时限制。

  • 顶层 await 只在 ES2022+ 模块中可用(如 type="module" 的 script 或 node.js 的 .mjs 文件),普通脚本仍不支持
  • async 函数返回值总是 Promise:即使你 return 123,实际返回的是 Promise.resolve(123)
  • 想在非 async 环境“用 await”,只能包一层:(async () => { const data = await api(); })()

错误处理必须用 try/catch,不能只靠 .catch()

await 把 Promise rejection 转成同步抛出的异常,所以 .catch() 无法捕获它——除非你在 await 后链式调用,但那就失去 await 的意义了。

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

正确写法:

async function loadData() {   try {     const res = await fetch('/api');     if (!res.ok) throw new Error(`HTTP ${res.status}`);     return await res.json();   } catch (err) {     console.error('加载失败:', err.message);     throw err;   } }

漏掉 try/catch 是最常导致未捕获异常崩溃的原因;尤其注意 await 后面的表达式本身也可能同步抛错(比如 await NULL.then())。

并发请求别盲目 await,小心变成串行

写成这样就错了:

const a = await fetch('/a'); const b = await fetch('/b'); // 等 a 完了才发 b

实际想并发,得先发起所有 Promise,再统一 await:

const [a, b] = await Promise.all([   fetch('/a'),   fetch('/b') ]);
  • Promise.allSettled 更适合容错场景(部分失败也要继续)
  • 大量并发时注意浏览器连接数限制(通常 6 个同域),Promise.all 失败会短路,allSettled 不会
  • 想控制并发数量(比如同时最多 3 个请求),得手写批处理逻辑,不能只靠 await

很多人以为 “用了 async/await 就天然支持并发”,其实恰恰相反——它默认倾向串行,需要主动打破。

text=ZqhQzanResources