javascript异步编程如何理解_promise和async_await怎样使用【教程】

10次阅读

promise封装未来完成或失败异步操作的对象,非语法糖或同步魔法;它立即执行 executor,通过 .then/.catch 处理结果,链式调用返回新 Promise;async/await 是其语法糖,await 不阻塞线程但需 try/catch 捕错。

javascript异步编程如何理解_promise和async_await怎样使用【教程】

Promise 是什么,不是什么

Promise 不是语法糖,也不是让异步变同步的魔法。它是一个对象,用来封装一个**尚未完成但未来会完成(或失败)的异步操作**,并提供统一的 .then()/.catch() 接口处理结果。

常见误解是把它当“等待器”——new Promise() 立即执行 executor 函数,内部的异步逻辑(比如 setTimeoutfetch)才决定 resolve/reject 的时机。Promise 本身不暂停代码执行。

  • 构造时传入的函数(executor)是同步运行的,但通常在里面启动异步任务
  • Promise.resolve(value)Promise.reject(reason) 用于快速创建已决议的 Promise
  • 链式调用中,每个 .then() 返回的是**新 Promise**,值传递靠 return,错误传递靠 throw 或返回 rejected Promise

async/await 是 Promise 的语法糖,不是新机制

async 函数必定返回 Promise,哪怕你写 return 42,实际返回的是 Promise.resolve(42)await 只是让 js 引擎在遇到 Promise 时暂停当前 async 函数的执行,等它 settled 后再继续——它不阻塞线程,也不影响事件循环

注意:await 只能在 async 函数内使用,顶层 await 仅在模块(type="module")中有效。

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

  • await 后面不强制是 Promise,非 Promise 值会被自动包装成 resolved Promise
  • 错误必须用 try/catch 捕获,.catch() 在 async 函数外才能接住抛出的异常
  • 多个独立请求别用 await 串行写,该用 Promise.all([p1, p2]) 并发

常见错误:混淆状态、忽略错误、滥用 await

最典型的问题是以为 await promise 能“修复”被 reject 的 Promise——其实它只是把 rejection 变成 throw,不 catch 就崩。

另一个高频坑是把本可并发的请求写成串行:

async function bad() {   const a = await fetch('/api/a').then(r => r.json());   const b = await fetch('/api/b').then(r => r.json()); // 等 a 完了才发 b   return [a, b]; }

正确做法是先发两个请求,再 await 它们的结果:

async function good() {   const [a, b] = await Promise.all([     fetch('/api/a').then(r => r.json()),     fetch('/api/b').then(r => r.json())   ]);   return [a, b]; }
  • 忘记处理 reject → 页面白屏或静默失败;加 try/catch 或在最后链 .catch(console.Error)
  • 在循环里直接 await → 实际是串行,性能差;需用 map().map(p => p.then(...))Promise.allSettled()
  • await 包裹已执行完的 Promise → 没必要,纯属多绕一层

调试 Promise 链和 await 的实际技巧

chromefirefox 控制台能显示 Promise 状态(pending/resolved/rejected),但不会显示中间 resolve 值。想看清每一步,要么加 console.log,要么用 async 函数拆分逻辑块。

node.js 中可通过 --trace-warnings 暴露未捕获的 Promise rejection;浏览器可用 window.addEventListener('unhandledrejection', ...) 兜底。

  • 链式调用过长时,优先拆成小的 async 函数,比 .then().then().then() 更易读
  • await Promise.resolve().then(...) 是无效延迟,等同于直接执行;真要微任务延迟,用 await Promise.resolve()
  • 测试时模拟 reject,别只 mock 成功路径;用 jest.mocksinon.stub().rejects() 覆盖错误分支

Promise 和 async/await 的核心差异不在能力,而在表达力与错误流控方式。真正卡住人的,往往不是“怎么写”,而是“什么时候不该用 await”“哪个 Promise 其实没被处理”。

text=ZqhQzanResources