JavaScript异步编程是应对单线程阻塞的生存策略,核心在于事件循环、任务队列与微任务优先机制,正确处理控制流、错误捕获和资源清理才是关键。

JavaScript 异步编程不是“学个新语法”,而是应对单线程阻塞的生存策略——你写的所有耗时操作(比如 fetch、setTimeout、文件读取、DOM 渲染等待)如果不异步,整个页面就卡死。
为什么 setTimeout 里的代码“看起来”后执行,但又不算真正延迟?
因为 setTimeout 把回调推入**任务队列**,而事件循环只在调用栈空了之后才去取它。哪怕你设成 0 毫秒,它也一定排在当前同步代码之后。
- 常见错误现象:
console.log('1'); setTimeout(() => console.log('2'), 0); console.log('3');输出是1 → 3 → 2,不是1 → 2 → 3 - 这不是“不准”,是 JavaScript 执行模型的必然结果:宏任务排队 + 微任务优先(
Promise.then就比setTimeout先跑) - 别用
setTimeout(fn, 0)当“让出主线程”的万能解;现代场景更推荐queueMicrotask或Promise.resolve().then
Promise.then 链和 await 的本质区别在哪?
await 看起来像暂停,其实只是 Promise 的语法糖,底层仍靠状态机驱动。但它强制你面对两个关键现实:
-
await只能在async函数里用,而.then()可以随处链;但滥用await会无意中把本可并发的操作变成串行(比如没用Promise.all) -
await后面如果不是 Promise,会被自动包装成Promise.resolve(value);但若你await null或await undefined,它不会报错,只是立即 resolve —— 容易掩盖逻辑漏洞 - 错误捕获方式不同:
.catch()是声明式兜底,try/catch是命令式拦截;后者对控制流更直观,但容易漏掉未 await 的 Promise(它们抛错不会进catch)
回调函数还没淘汰,但什么场景还必须用它?
不是所有异步都走 Promise 路线。有些原生 API 依然只收回调,比如:
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。它不是新的编程语言,而是一种使用现有标准的新方法,最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容,不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。《php中级教程之ajax技术》带你快速
立即学习“Java免费学习笔记(深入)”;
-
addEventListener:DOM 事件不返回 Promise,重复绑定多个监听器也没问题;想转成 Promise 可封装,但得自己处理移除逻辑(避免内存泄漏) -
Node.js的老式fs.readFile(非fs.promises版):回调第一参数约定为err,这是 Node 错误优先(error-first)风格,不能直接await - 第三方库的钩子(如
canvas.toBlob(callback)、某些 WebRTC 方法):没有 Promise 包装,强行 Promisify 要小心 this 绑定和多次调用风险
真实项目里,最常踩的坑不是“不会写 async”,而是混用模式导致控制流断裂:比如在 async 函数里忘了 await 一个 Promise,或者用 .then() 处理本该用 try/catch 捕获的网络异常。异步的本质不是“怎么写”,是“谁负责清理、谁承担失败、谁决定重试”。










