async和await怎样简化javascript异步【教程】

6次阅读

async/await 是 promise 链的可读性补丁,不改变异步本质;async 函数必返回 Promise,await 仅限 async 内部使用,错误需显式 await + try/catch,多请求应依业务选串行或 Promise.all 并发

async和await怎样简化javascript异步【教程】

async/await 不是语法糖的替代品,而是 Promise 链的可读性补丁——它不能消除异步本质,但能让你少写 .then().catch(),也避免掉进 Promise 嵌套或忘记 return 的坑。

async 函数必须显式返回 Promise 才能被 await 消费

很多人以为只要加了 async,函数就“自动变异步”,其实不然:async 只保证函数返回一个 Promise(哪怕你 return 42,也会被包装成 Promise.resolve(42))。但如果你在函数里调用的是普通同步函数、或者忘了 await 一个 Promise,那后续逻辑仍会同步执行。

  • async function foo() { return fetch('/api'); } → 返回的是 Promise,没问题
  • async function bar() { fetch('/api'); return 'done'; }fetch 被丢弃,'done' 立即被包装成 resolved Promise,API 请求实际没等
  • 正确写法是:async function bar() { const res = await fetch('/api'); return res.json(); }

await 只能在 async 函数内部使用

这是常见报错源头:Uncaught SyntaxError: await is only valid in async function。你不能在顶层模块代码、普通函数、事件回调(如 button.onclick = () => { await fn(); })里直接写 await,除非那个函数本身被声明为 async

  • 浏览器中顶层 await 仅在 ES 模块(type="module")下可用,且只限于模块作用域,不适用于普通
  • setTimeout(() => { await doAsync(); }, 100); ❌ 报错;得写成 setTimeout(async () => { await doAsync(); }, 100);
  • react 事件处理函数常用写法:const handleClick = async () => { await submitForm(); }

错误处理别只靠 try/catch,小心未捕获的 Promise rejection

await 会让 rejected Promise 变成同步抛出的异常,所以 try/catch 能捕获。但这只覆盖你显式 await 的那一层。如果某个 Promise 在 async 函数里被创建却没被 await,又没加 .catch(),它就会变成 unhandled rejection。

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

  • async function bad() { fetch('/fail').catch(err => console.error(err)); } → 安全,错误被吞掉
  • async function worse() { fetch('/fail'); } → 即使函数是 async,这个 Promise 仍可能触发 unhandledrejection 事件
  • 推荐模式:try { const data = await fetch(...).then(r => r.json()); } catch (e) { /* 处理网络或解析错误 */ }

await 并不“阻塞线程”,但会暂停当前 async 函数的执行流

这是最容易误解的一点:JS 仍是单线程、非阻塞的。await 只是让 JS 引擎把当前函数挂起,把控制权交还给事件循环,等 Promise settled 后再从暂停处继续。这意味着:

  • 多个 await 默认是串行的,不是并行的 —— await a(); await b(); 意味着 b() 必须等 a() 完全结束
  • 想并发?得用 Promise.all([a(), b()]),再 await Promise.all([...])
  • 过度使用 await 在无关操作间会造成不必要延迟,比如本可以并行的 API 请求被写成串行

真正难的从来不是写 async/await,而是判断哪几个异步操作该串行、哪几个该并发、以及 Promise 生命周期里哪一环该负责错误清理。这些没法靠语法自动解决,得看业务逻辑本身是否允许重叠或降级。

text=ZqhQzanResources