javascript的async和await是什么_如何简化异步代码【教程】

11次阅读

async/await 是基于 promise 的语法糖,使异步代码更易读;async 函数自动返回 Promise,await 暂停函数执行但不阻塞线程,需在 async 函数内使用,支持 thenable 对象,错误可用 try/catch 捕获,并发请求应避免串行化。

javascript的async和await是什么_如何简化异步代码【教程】

asyncawaitjavaScript 中处理异步操作的语法糖,本质是基于 Promise封装。它们不改变异步本质,但让异步代码写起来像同步代码,可读性更强、错误处理更直观。

async 函数必须返回 Promise

声明一个函数为 async,它就自动包装返回值为 Promise。即使你 return 42,实际返回的是 Promise.resolve(42);如果抛错,则等价于 Promise.reject(err)

常见误区:以为 async 让函数“变同步”了——其实只是让 await 能暂停当前函数执行(仅限该函数内部),外部调用仍是异步的。

  • async 函数内部可以没有 await,但仍有 Promise 包装行为
  • 不能在普通函数或顶层作用域中直接使用 await,必须在 async 函数内
  • 箭头函数也可 asyncconst fetchUser = async () => { ... }

await 只能等待 thenable 对象

await 后面的表达式会被自动调用 .then(),所以它接受任何 Promise 或拥有 .then() 方法的对象(比如 jqueryDeferred,或某些旧库的类 Promise 实例)。

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

但要注意:

  • 如果等的是普通值(如 await 123),会立即 resolve,等效于 Promise.resolve(123)
  • 如果等的是 NULLundefined 或没 .then 的对象,会报 TypeError: xxx is not a thenable
  • await 不会“阻塞线程”,只是暂停当前 async 函数的执行,js 引擎继续跑其他任务

错误处理:try/catch 比 .catch() 更自然

await 时,异步错误可以直接用 try/catch 捕获,不需要链式 .catch(),嵌套深时优势明显。

async function loadConfig() {   try {     const res = await fetch('/api/config');     if (!res.ok) throw new Error(`HTTP ${res.status}`);     return await res.json();   } catch (err) {     console.error('加载配置失败:', err.message);     throw err; // 重新抛出以便上层处理   } }

注意点:

  • catch 会捕获 await 表达式 reject 的 Promise,也包括 throw 的同步错误
  • 多个 await 写在同一 try 块里,任一失败都会进 catch,无法区分是哪个出错——需要拆分或加日志
  • 不要在 await 后直接接 .catch()(如 await fn().catch(...)),这会让错误“吞掉”,catch 块拿不到原始错误

并发请求:避免无脑 await 导致串行化

连续写多个 await 会让请求变成串行,哪怕它们彼此无关。想并发,得先触发所有 Promise,再统一 await

async function fetchBoth() {   // ❌ 串行:第二个请求要等第一个完成   const user = await fetch('/user');   const posts = await fetch('/posts');    // ✅ 并发:两个请求同时发出   const [userRes, postsRes] = await Promise.all([     fetch('/user'),     fetch('/posts')   ]);   return { user: await userRes.json(), posts: await postsRes.json() }; }

关键区别

  • Promise.all 失败时会短路(任一 reject 就 reject 整个),需用 Promise.allSettled 处理部分失败场景
  • 浏览器并发请求数有限制(通常 6~8 个),大量并行可能触发限流或超时
  • 如果请求有依赖关系(比如用 Token 换用户信息),才必须串行 await

真正容易被忽略的不是语法,而是对事件循环的理解:await 不是“停住 JS”,而是“把后续逻辑注册为微任务,让出执行权”。一旦搞混这点,就会在调试竞态条件、定时器、或与 setTimeout 交互时踩坑。

text=ZqhQzanResources