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

发布时间 - 2026-01-27 00:00:00    点击率:
async/await 是 Promise 链的可读性补丁,不改变异步本质;async 函数必返回 Promise,await 仅限 async 内部使用,错误需显式 await + try/catch,多请求应依业务选串行或 Promise.all 并发。

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。

  • 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 生命周期里哪一环该负责错误清理。这些没法靠语法自动解决,得看业务逻辑本身是否允许重叠或降级。


# react  # javascript  # java  # js  # json  # 浏览器  # ai  # 作用域  # try  # catch  # Error  # const  # 循环  # 线程  # 并发 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 奇安信“盘古石”团队突破 iOS 26.1 提权  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  清除minerd进程的简单方法  html文件怎么打开证书错误_https协议的html打开提示不安全【指南】  千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】  魔毅自助建站系统:模板定制与SEO优化一键生成指南  Laravel Admin后台管理框架推荐_Laravel快速开发后台工具  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  Mybatis 中的insertOrUpdate操作  邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?  canvas 画布在主流浏览器中的尺寸限制详细介绍  bing浏览器学术搜索入口_bing学术文献检索地址  简历没回改:利用AI润色让你的文字更专业  Laravel 419 page expired怎么解决_Laravel CSRF令牌过期处理  Laravel安装步骤详细教程_Laravel环境搭建指南  Laravel如何实现全文搜索功能?(Scout和Algolia示例)  Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】  Laravel事件和监听器如何实现_Laravel Events & Listeners解耦应用的实战教程  ,南京靠谱的征婚网站?  javascript基于原型链的继承及call和apply函数用法分析  Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置  如何快速辨别茅台真假?关键步骤解析  如何将凡科建站内容保存为本地文件?  如何在宝塔面板中修改默认建站目录?  Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID  如何在IIS服务器上快速部署高效网站?  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  Laravel如何为API生成Swagger或OpenAPI文档  原生JS实现图片轮播切换效果  javascript事件捕获机制【深入分析IE和DOM中的事件模型】  Laravel如何配置和使用缓存?(Redis代码示例)  矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤  Laravel如何使用Telescope进行调试?(安装和使用教程)  大连网站制作公司哪家好一点,大连买房网站哪个好?  Bootstrap整体框架之CSS12栅格系统  Laravel怎么调用外部API_Laravel Http Client客户端使用  Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明  Laravel如何发送邮件_Laravel Mailables构建与发送邮件的简明教程  海南网站制作公司有哪些,海口网是哪家的?  怎样使用JSON进行数据交换_它有什么限制  Linux系统命令中tree命令详解  国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?  微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】  如何快速搭建高效香港服务器网站?  PHP 500报错的快速解决方法  Laravel如何实现多语言支持_Laravel本地化与国际化(i18n)配置教程  实现点击下箭头变上箭头来回切换的两种方法【推荐】  如何在云主机上快速搭建网站?  北京的网站制作公司有哪些,哪个视频网站最好?