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

相关推荐
葡萄城技术团队5 分钟前
当表格数据来自外部系统:SpreadJS 如何让异步公式一键刷新
前端
小徐_23339 分钟前
Open Wot 1.0.5 发布:让 AI 接入 wot-ui,只需要两条命令
前端·uni-app·ai编程
Android研究员13 分钟前
Android进阶之事件分发机制深度剖析
android·前端·面试
Csvn20 分钟前
🛡️ 前端水印方案全解析——从「能被 F12 删掉」到「删不掉」的反破解实战
前端
学网安的肆伍1 小时前
【046-WEB攻防篇】注入工具&SQLMAP&Tamper编写&指纹修改&高权限操作&目录架构
前端·架构
森林的尽头是阳光1 小时前
tree回显问题
javascript·vue.js·elementui
weixin_BYSJ19872 小时前
「课设设计」springboot校园超市助购系统26449 (附源码)
java·javascript·spring boot·python·django·flask·php
Highcharts.js2 小时前
如何下载使用Highcharts Grid 开发web可编辑表格
前端·人工智能·grid 表格·web 表格·在线编辑表格·highcharts表格安装·表格开发工具
用户62960593247053 小时前
从“浏览器根本区分不了”到真正实现:刷新不退出,关闭标签页自动退出,前端判断浏览器关闭和刷新
前端
qetfw3 小时前
MWU:Vue 3 + FastAPI 的 MaaFramework 跨平台 WebUI 源码
前端·vue.js·python·fastapi·开源项目·效率工具