红宝书第十七讲:通俗详解JavaScript的Promise与链式调用


红宝书第十七讲:通俗详解JavaScript的Promise与链式调用

资料取自《JavaScript高级程序设计(第5版)》。 查看总目录:红宝书学习大纲


一、Promise的作用:解决"回调地狱"的困境

Promise(承诺)是JavaScript管理异步操作 的工具,用于替代传统的嵌套回调链(回调地狱)。它能将异步代码线性化 ,让异步逻辑像步骤说明书一样清晰 ^1^[^4]。

传统回调地狱的代码(难以阅读和维护):

javascript 复制代码
// 示例:依次执行多个异步任务(层层嵌套的"金字塔")
delayedExecute('第一步', (result1) => {
  delayedExecute('第二步', (result2) => {
    delayedExecute('第三步', (result3) => { // 层层缩进 → 难以维护
      // ...
    });
  });
});

Promise链式调用的代码(清晰易读):

javascript 复制代码
fetchData()
  .then((result1) => process(result1))  // 步骤1
  .then((result2) => process(result2))  // 步骤2
  .then((result3) => process(result3))  // 步骤3
  .catch((error) => console.error(error)); // 统一错误处理

^[1](#1: 资料2提到Promise/A+规范用于统一异步编程模式 "#user-content-fn-2")^: 资料2提到Promise/A+规范用于统一异步编程模式
^[2](#2: 资料5对比回调地狱与Promise链式调用的代码结构优势 "#user-content-fn-5")^: 资料5对比回调地狱与Promise链式调用的代码结构优势


二、Promise的状态:3个阶段

每个Promise对象有3种状态 ^1^:

  1. Pending(等待中):初始状态,尚未完成
  2. Fulfilled(已成功):异步操作成功完成
  3. Rejected(已失败):异步操作失败或出现错误

三、链式调用:像流水线一样处理异步任务

链式调用的核心在于:每个then()/catch()/finally()都会返回一个新的Promise ,允许后续继续调用 ^3^^2^。

示例:分步骤模拟异步操作
javascript 复制代码
// 创建返回Promise的简单异步函数
function delay(ms, value) {
  return new Promise((resolve) => {
    setTimeout(() => resolve(value), ms);
  });
}

// 链式调用示例 → 每个then等待前一步完成
delay(1000, "第一步数据")
  .then((data) => {
    console.log(`收到:${data}`);
    return delay(1000, "第二步处理后的数据"); // 返回新Promise
  })
  .then((data) => {
    console.log(`收到:${data}`);
    return "直接返回的第三步结果(非Promise)";
  })
  .then(console.log); // 自动包装为已成功的Promise

// 输出:
// (1秒后)收到:第一步数据
// (2秒后)收到:第二步处理后的数据
// (2秒后)直接返回的第三步结果...

^[3](#3: 资料1说明then/catch的链式返回新Promise对象 "#user-content-fn-1")^: 资料1说明then/catch的链式返回新Promise对象
^[2](#2: 资料5展示通过then链式严格排序的异步执行 "#user-content-fn-5")^: 资料5展示通过then链式严格排序的异步执行

流程图解释链式调用:
flowchart LR start[启动Promise] --> F1[执行第一个then] F1 --> 成功?{是否成功} 成功? -- 是 --> F2[执行第二个then] 成功? -- 否 --> Catch[执行catch处理] F2 --> 成功2?{是否成功} 成功2? -- 是 --> F3[执行第三个then] 成功2? -- 否 --> Catch Catch --> Finally[执行finally清理]

四、错误处理:统一捕获异常

通过catch()集中处理链中的任何错误,不影响后续步骤 ^3^^4^。

示例:错误捕获后继续执行
javascript 复制代码
fetchData()
  .then(processStep1) 
  .then(() => { throw new Error("故意抛出错误"); }) // 中途出错
  .catch((error) => { 
    console.error(`捕获错误:${error}`);
    return "错误后的恢复数据"; 
  })
  .then((data) => console.log(`继续处理:${data}`)); // 继续链式

// 输出:
// 捕获错误:故意抛出错误
// 继续处理:错误后的恢复数据

^[4](#4: 资料6中通过catch处理多个请求的集合错误 "#user-content-fn-6")^: 资料6中通过catch处理多个请求的集合错误


五、应用场景与扩展知识

  1. 多个异步任务并行Promise.all([任务1, 任务2]))^4^
  2. 仅需第一个完成的任务 (如竞速请求:Promise.any([任务1, 任务2]))^4^
  3. 统一清理资源finally(() => { ... }),无论成功失败都会执行)

目录:总目录 上篇文章:红宝书第十六讲:通俗详解JavaScript回调函数与事件循环

脚注

Footnotes

  1. 《JavaScript高级程序设计(第5版)》提及Promise状态机与异步编程模式 2 3

  2. 《JavaScript高级程序设计(第5版)》对比传统回调与Promise链式代码结构 2 3

  3. 《JavaScript高级程序设计(第5版)》指出链式调用基于每个方法返回新Promise 2 3

  4. 《JavaScript高级程序设计(第5版)》说明使用Promise.any()处理最快响应结果 2 3 4

相关推荐
程序猿阿伟30 分钟前
《社交应用动态表情:RN与Flutter实战解码》
javascript·flutter·react native
明似水32 分钟前
Flutter 开发入门:从一个简单的计数器应用开始
前端·javascript·flutter
沐土Arvin37 分钟前
前端图片上传组件实战:从动态销毁Input到全屏预览的全功能实现
开发语言·前端·javascript
Zww08911 小时前
el-dialog鼠标在遮罩层松开会意外关闭,教程图文并茂
javascript·vue.js·计算机外设
爱编程的鱼1 小时前
C#接口(Interface)全方位讲解:定义、特性、应用与实践
java·前端·c#
sunbyte1 小时前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | 页面布局 与 Vue Router 路由配置
前端·javascript·vue.js·tailwindcss
saadiya~2 小时前
Vue 3 实现后端 Excel 文件流导出功能(Blob 下载详解)
前端·vue.js·excel
摇摇奶昔x3 小时前
webpack 学习
前端·学习·webpack
阿珊和她的猫3 小时前
Vue Router中的路由嵌套:主子路由
前端·javascript·vue.js