回调函数 vs Promise vs async/await区别

回调函数(Callback)、Promise 和 async/await 都是 JavaScript 中处理 异步编程 的方式。

一、定义和基本写法

1. 回调函数(Callback)

概念:

把一个函数作为参数传给另一个函数,当异步操作完成后,再调用这个函数。

示例:

javascript 复制代码
function fetchData(callback) {
  setTimeout(() => {
    callback("数据已加载");
  }, 1000);
}

fetchData(function (data) {
  console.log(data); // 输出:数据已加载
});
  • 优点:

    • 语法简单,广泛使用。
  • 缺点:

    • 容易出现"回调地狱"或"嵌套地狱"。

    • 错误处理繁琐,容易遗漏。

2. Promise

概念:

Promise 是一个代表未来值的对象。它有三种状态:pending(进行中)、fulfilled(成功)、rejected(失败)。

示例:

javascript 复制代码
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("数据已加载");
      // 或者 reject("加载失败");
    }, 1000);
  });
}

fetchData()
  .then((data) => console.log(data))      // 成功处理
  .catch((err) => console.error(err))     // 错误处理
  .finally(() => console.log("结束"));    // 无论成功或失败都执行
  • 优点:

    • 链式调用,减少嵌套。

    • 内置 .then(), .catch(), .finally() 更好组织代码。

  • 缺点:

    • 多层 .then() 嵌套仍然不够直观。

    • 错误捕获仍需特别注意。

3. async / await

概念:

是基于 Promise 的语法糖,让异步代码写起来更像同步,更简洁清晰。

示例:

javascript 复制代码
function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("数据已加载");
    }, 1000);
  });
}

async function getData() {
  try {
    const data = await fetchData();
    console.log(data); // 输出:数据已加载
  } catch (err) {
    console.error(err); // 错误捕获
  } finally {
    console.log("结束");
  }
}

getData();
  • 优点:

    • 更接近同步代码的书写方式,逻辑更清晰。

    • 错误处理使用 try/catch,和同步代码一致。

  • 缺点:

    • 不能用在顶层作用域中(必须放在 async 函数里)。

    • 同时执行多个异步任务时不如 Promise.all 等组合方法直观。

二、优缺点对比

特性 回调函数 Promise async/await
引入年代 最早 ES6(2015) ES8(2017)
可读性 差(容易嵌套) 中等(链式) 高(接近同步代码)
控制流程 回调地狱(嵌套多层) 链式调用 .then() 线性流程,最直观
错误处理 不统一(靠手动处理) .catch() 统一处理 try/catch 统一处理
取消操作 不方便 可结合 AbortController 可结合 AbortController
并发执行 复杂 Promise.all 等很方便 可搭配 Promise 并发执行
兼容性 老浏览器兼容好 IE11 及以上 需要 Babel 转码支持

三、使用场景推荐

场景 推荐用法
旧项目/库或兼容性要求高 回调函数
多个异步并发或链式处理 Promise
写异步流程、结构清晰、易维护 async / await

四、实际对比举例

  • 回调嵌套(回调地狱)
javascript 复制代码
getUser(id, function(user) {
  getPosts(user.id, function(posts) {
    getComments(posts[0].id, function(comments) {
      console.log(comments);
    });
  });
});
  • Promise 链式优化
javascript 复制代码
getUser(id)
  .then(user => getPosts(user.id))
  .then(posts => getComments(posts[0].id))
  .then(comments => console.log(comments))
  .catch(err => console.error(err));
  • async/await 优雅写法
javascript 复制代码
async function showComments(id) {
  try {
    const user = await getUser(id);
    const posts = await getPosts(user.id);
    const comments = await getComments(posts[0].id);
    console.log(comments);
  } catch (err) {
    console.error(err);
  }
}

五、总结

  • 回调函数 是最原始的异步方式,但会导致 回调地狱。

  • Promise 更加优雅,支持 链式调用与统一错误处理。

  • async/await 是基于 Promise 的语法糖,让异步代码写得像同步一样,可读性最强。

相关推荐
sheepwjl1 分钟前
《嵌入式C语言笔记(十七):进制转换、结构体与位运算精要》
linux·c语言·开发语言·笔记·算法
optimistic_chen2 分钟前
【Java EE初阶 --- 网络原理】网络层---IP协议,数据链路层---以太网协议
网络·笔记·网络协议·tcp/ip·java-ee·文件io
源代码•宸17 分钟前
深入浅出设计模式——创建型模式之单例模式 Singleton
开发语言·c++·经验分享·单例模式·设计模式
fsnine23 分钟前
网络爬虫(python)入门
开发语言·爬虫·python
WilliamHu.25 分钟前
金融分类提示词演示
开发语言·python·大模型·prompt
就改了27 分钟前
npm从入门到精通一篇全
javascript
朴shu28 分钟前
Luckysheet 打印终极指南(预览视图+打印功能) : 2025 最新实现
前端·javascript·html
YGY Webgis糕手之路28 分钟前
Cesium 快速入门(三)Viewer:三维场景的“外壳”
前端·经验分享·笔记·vue·web
拾光拾趣录29 分钟前
模拟场景 | 前端常见问题
前端
不可描述的两脚兽35 分钟前
学习笔记《区块链技术与应用》第4天 比特币脚本语言
笔记·学习·区块链