回调函数 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 的语法糖,让异步代码写得像同步一样,可读性最强。

相关推荐
微风中的麦穗3 小时前
【MATLAB】MATLAB R2025a 详细下载安装图文指南:下一代科学计算与工程仿真平台
开发语言·matlab·开发工具·工程仿真·matlab r2025a·matlab r2025·科学计算与工程仿真
2601_949146534 小时前
C语言语音通知API示例代码:基于标准C的语音接口开发与底层调用实践
c语言·开发语言
开源技术4 小时前
Python Pillow 优化,打开和保存速度最快提高14倍
开发语言·python·pillow
学嵌入式的小杨同学4 小时前
从零打造 Linux 终端 MP3 播放器!用 C 语言实现音乐自由
linux·c语言·开发语言·前端·vscode·ci/cd·vim
weixin_425543734 小时前
TRAE CN3.3.25 构建的Electron简易DEMO应用
前端·typescript·electron·vite·nestjs
Mr Xu_5 小时前
【Vue3 + ECharts 实战】正确使用 showLoading、resize 与 dispose 避免内存泄漏
前端·信息可视化·vue·echarts
mftang5 小时前
Python 字符串拼接成字节详解
开发语言·python
0思必得05 小时前
[Web自动化] Selenium设置相关执行文件路径
前端·爬虫·python·selenium·自动化
雯0609~6 小时前
hiprint:实现项目部署与打印1-官网提供普通html版本
前端·html
jasligea6 小时前
构建个人智能助手
开发语言·python·自然语言处理