红宝书第十七讲:通俗详解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

相关推荐
小新讲网安3 分钟前
HTTP请求走私攻击实战:CL.TE与TE.CL绕过前端服务器全解析
服务器·前端·网络·web安全·http·架构·漏洞
风骏时光牛马7 分钟前
AI办公系统异常事件复盘分析
前端
console.log('npc')10 分钟前
React 19 + Vite 企业级前端项目:从零搭建到规范交付
前端·react.js·前端框架
程序员黑豆15 分钟前
Java字符串常量池完全指南:原理、intern()方法与性能优化最佳实践
java·前端·ai编程
光影少年16 分钟前
react离线缓存、图片缓存方案
开发语言·前端·javascript·react native·react.js·缓存·前端框架
Canace22 分钟前
笔记本都合上了,Claude 为什么还能在手机上执行电脑上装的技能?
前端·人工智能·ai编程
cyadyx1 小时前
Vite 比 Webpack 构建效率更高
前端·webpack·node.js·vite
mCell3 小时前
AI 时代 SVG 画图的潜力
前端·agent·svg
我命由我123459 小时前
CesiumJS 笔记 - 获取容器中心点、Cartesian3 clone 方法、修改 Cartesian3 对象的高度
前端·javascript·css·前端框架·html·html5·js
Hopebearer_10 小时前
页面突然只剩 DOM?一次静态资源版本错配排查
前端·部署