JavaScript 的异步编程核心是避免阻塞主线程,让耗时操作(如网络请求、文件读取、定时器)不卡住页面。回调函数和 Promise 都是用来处理异步任务的机制,但设计思想、可读性、错误处理和组合能力差别明显。

回调函数:最基础的异步表达方式
回调函数是把一个函数作为参数传给另一个函数,在异步操作完成后由该函数“回头调用”。比如:
setTimeout(() => console.log('执行完了'), 1000);常见问题包括:
回调地狱(Callback Hell):多层嵌套导致代码向右偏移严重,难以阅读和维护
错误处理分散:每个回调都要单独检查 error,容易遗漏
无法用 try/catch 捕获异步错误:因为回调执行时机不在当前同步上下文中
控制流难管理:比如并发多个请求、顺序执行、取消操作都需手动实现
Promise:更规范的异步对象封装
Promise 是一个代表异步操作最终完成或失败的对象,有三种状态:pending(进行中)、fulfilled(成功)、rejected(失败)。创建后状态不可逆,且只能改变一次。
它通过 .then() 和 .catch() 统一处理成功与失败,支持链式调用:
fetch('/api/data')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error('出错了', err));优势包括:
扁平化结构:避免深层嵌套,逻辑更线性
错误冒泡:任意 .then 中抛错都会被后续 .catch 捕获
组合能力更强:Promise.all()、Promise.race() 等原生方法简化并发控制
可被 async/await 消费:为现代异步写法打下基础
关键区别一句话总结
回调函数是“你告诉我做完后怎么处理”,属于过程式思维;Promise 是“我给你一个承诺对象,你随时可以决定怎么响应结果”,属于声明式、可组合的对象模型。Promise 不是替代回调,而是对回调模式的抽象升级——它内部仍可能使用回调,但对外提供了更可靠、更易维护的接口。
实际选择建议
新项目优先用 async/await + Promise,语义清晰、调试友好
封装底层 API(如自定义 fetch 封装)时,直接返回 Promise,不要暴露回调参数
对接老库(如 Node.js 早期 fs 模块)时,可用 Promisify 工具转成 Promise 版本
极简场景(如单个 setTimeout)用回调也无妨,但别让它蔓延成链
标签: javascript




还木有评论哦,快来抢沙发吧~