跳到正文

事件循环与异步 ​

  • 状态:未准备
  • 适用方向:前端 / Go 全栈
  • 最近复习:待填写
  • 下次复习:待安排

一句话回答 ​

浏览器在当前 JavaScript 执行结束后的微任务检查点清空微任务,再继续调度任务和可能的渲染;Promise 回调与 await 后续通过异步调度执行,异步不代表计算自动并行。

原理解释 ​

典型输出题 ​

js
console.log('A')
setTimeout(() => console.log('B'), 0)
Promise.resolve().then(() => console.log('C'))
async function run() {
  console.log('D')
  await 0
  console.log('E')
}
run()
console.log('F')
// A D F C E B

先执行同步部分;C 的反应先入微任务队列,await 的后续随后排队;计时器回调是后续任务。浏览器有不同任务来源,并非一个全局严格 FIFO 的“宏任务队列”。渲染不保证在每次任务后发生;持续生成微任务可能阻塞交互与绘制。

Promise 的核心规则 ​

构造器 executor 同步执行,then/catch 回调异步执行。then 返回新 Promise:返回普通值会兑现下游,抛错使下游拒绝,返回 Promise/thenable 会采用其结果。Promise 一旦落定不能再次改变;调用 resolve 采用另一个尚未落定的 Promise 时,不代表立即 fulfilled。

并发组合怎么选? ​

  • all:全部成功才成功,一个拒绝就拒绝,成功结果按输入顺序。
  • allSettled:等待所有结果,适合独立任务汇总。
  • race:采用最先落定的结果。
  • any:采用最先兑现的结果,全部拒绝时以 AggregateError 拒绝。

场景与边界 ​

await 会暂停当前 async 函数的后续执行,不阻塞整个主线程。Promise.all 不自动取消剩余任务;fetch 可通过 AbortController 请求取消。重 CPU 计算需要拆分或使用 Worker,而不是包一层 Promise。

项目中的应用 ​

结合 SimulSpeak 媒体授权与停止竞态,解释“发起后用户停止,异步操作仍可能稍后完成”,清理逻辑应覆盖晚到资源。

常见追问 ​

  • setTimeout 0 是立即吗? 只是达到调度条件后等待执行,实际延迟还受当前任务、节流等影响。
  • try/catch 能捕获 Promise 拒绝吗? await 放在 try 内可以;只创建 Promise 而不等待,外层同步 try/catch 无法接住之后的拒绝。
  • rAF 是微任务吗? 不是,它参与浏览器渲染更新调度,不能按 Promise 微任务理解。

参考资料 ​

理解机制,讲清取舍,用复盘检验掌握。