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

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


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

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

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

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

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

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

1: 资料2提到Promise/A+规范用于统一异步编程模式
2: 资料5对比回调地狱与Promise链式调用的代码结构优势


二、Promise的状态:3个阶段

每个Promise对象有3种状态 1

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

Promise状态机示意图


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

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

示例:分步骤模拟异步操作
// 创建返回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: 资料1说明then/catch的链式返回新Promise对象
2: 资料5展示通过then链式严格排序的异步执行

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

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

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

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

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

4: 资料6中通过catch处理多个请求的集合错误


五、应用场景与扩展知识

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

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

下篇文章:红宝书第十八讲:详解JavaScript的async/await与错误处理

脚注


  1. 《JavaScript高级程序设计(第5版)》提及Promise状态机与异步编程模式
  2. 《JavaScript高级程序设计(第5版)》对比传统回调与Promise链式代码结构
  3. 《JavaScript高级程序设计(第5版)》指出链式调用基于每个方法返回新Promise
  4. 《JavaScript高级程序设计(第5版)》说明使用Promise.any()处理最快响应结果

kovli
10 声望4 粉丝