JavaScript异步处理应依场景选择:回调适用于简单链式调用,Promise统一状态与错误传播,async/await是其语法糖,降低嵌套负担;三者常混用,需注意错误边界。
JavaScript 异步处理不是选哪个“更高级”,而是看场景和协作成本:回调适合简单链式调用,Promise 是错误处理和组合的分水岭,async/await 本质是 Promise 语法糖,但大幅降低嵌套和 .then() 的心智负担。
回调本身没有错,错在多层嵌套 + 错误分散时难以维护。典型现象是“回调地狱”(callback hell):缩进越来越深、错误处理重复、无法用 return 或 try/catch 统一捕获。
undefined 或变量覆盖setTimeout、fs.readFile(Node.js)这类 API 的回调参数顺序不统一(如 Node 回调是 (err, data),而浏览器 addEventListener 没有 err)for...of 或 map 直接处理多个异步任务,必须手写循环+计数器Promise 把“异步结果”变成可传递、可组合的一等公民,核心价值不在写法,而在统一了状态(pending/fulfilled/rejected)和错误传播路径。
.then() 和 .catch() 总是异步执行(微任务),与同步代码严格分离,避免竞态.then() 返回非 Promise 值会自动包装,返回 Promise 则等待其完成 —— 这是组合多个异步操作的基础Promise.all() 遇到任一拒绝就短路,需用 Promise.allSettled() 获取全部结果async 函数返回值一定是 Promise,await 只是暂停当前函数执行,等右侧表达式(必须是 Promise 或 thenable)完成后再继续 —— 它不能脱离 Promise 生态单独工作。
async 函数内使用 await,否则报 SyntaxError: await is only valid in async function
await 后面如果不是 Promise,会自动转成 Promise.resolve(value),所以 await 123 是合法的try/catch 捕获,catch 块能拿到被 reject 的值,但不会自动吞掉错误 —— 这点比回调更可控await a(); await b();(串行),应先 const [aRes, bRes] = await Promise.all([a(), b()])
没有银弹。现代代码里混用很常见:库内部可能暴露 Promise,上层用 async/await 消费;遗留回

new Promise() 包一层再 await。
async/await,尤其涉及条件分支、循环或错误恢复时Promise.race() 实现超时)、或做复杂组合(Promise.allSettled() + 过滤)时,直接操作 Promise 更清晰addEventListener)、Node.js 流(stream.on('data', ...))仍是回调驱动,强行 Promise 化反而增加开销最容易被忽略的是错误边界 —— async/await 中漏写 try/catch,或 Promise 链末尾没加 .catch(),都会让错误静默失败,尤其在生产环境难以定位。