Promise的链式调用

概念

Promise的链式调用是指在一个Promise对象上连续调用多个then方法的过程。通过链式调用,可以将多个异步操作按照顺序执行,并且可以在每个操作完成后处理返回的结果。

当使用Promise进行链式调用时,每个then方法都可以接收两个参数:一个是成功回调函数,一个是失败回调函数。成功回调函数用于处理上一个Promise对象的成功状态,而失败回调函数用于处理上一个Promise对象的失败状态。

在链式调用中,每个then方法都会返回一个新的Promise对象。这个新的Promise对象的状态和值取决于上一个Promise对象的状态和值以及当前then方法中的回调函数返回值。

如果在某个then方法中返回了一个普通值(非Promise对象),那么新的Promise对象会立即进入成功状态,并且其值为这个普通值。

如果在某个then方法中返回了一个Promise对象,那么新的Promise对象会等待这个返回的Promise对象进入完成状态(即成功或失败),然后根据返回的结果进入相应的状态。

示例一

下面是一个更详细的例子来说明Promise链式调用:

javascript 复制代码
function asyncOperation1() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Operation 1 completed');
    }, 1000);
  });
}

function asyncOperation2() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Operation 2 completed');
    }, 2000);
  });
}

function asyncOperation3() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Operation 3 completed');
    }, 1500);
  });
}

asyncOperation1()
  .then(result1 => {
    console.log(result1);
    return asyncOperation2();
  })
  .then(result2 => {
    console.log(result2);
    return asyncOperation3();
  })
  .then(result3 => {
    console.log(result3);
    console.log('All operations completed');
  })
  .catch(error => {
    console.error('An error occurred:', error);
  });

在上面的例子中,我们定义了三个异步操作函数asyncOperation1asyncOperation2asyncOperation3,它们分别模拟了三个异步操作。

首先,我们调用asyncOperation1()来开始链式调用。在第一个then 方法中,我们打印出了第一个操作的结果,并返回了asyncOperation2()Promise对象。

接着,在第二个then 方法中,我们打印出了第二个操作的结果,并返回了asyncOperation3()Promise对象。

最后,在第三个then方法中,我们打印出了第三个操作的结果,并输出了所有操作完成的消息。

如果在整个链式调用过程中发生了错误(比如某个异步操作失败),则会跳过后续的then方法,直接进入最近的catch 方法。在catch方法中可以处理错误并进行相应的处理。

通过链式调用,我们可以按照顺序执行多个异步操作,并在每个操作完成后处理返回的结果。这样可以避免回调地狱,并且使代码更加清晰和易读。同时,通过使用catch方法可以捕获和处理错误,提高代码的健壮性。

示例二

链式调用在处理异步操作的场景中非常有用,可以实现一系列操作的顺序执行和错误处理。对于尝试请求事件,失败继续请求,失败n次后不再请求的场景,可以通过链式调用来实现。

下面是一个示例代码来说明如何使用Promise链式调用来实现这个场景:

javascript 复制代码
function makeRequest() {
  return new Promise((resolve, reject) => {
    // 模拟请求
    setTimeout(() => {
      // 假设请求成功
      const success = Math.random() < 0.3;
      if (success) {
        resolve('Request succeeded');
      } else {
        reject('Request failed');
      }
    }, 1000);
  });
}

function retryRequest(maxAttempts) {
  let attempts = 0;

  function tryRequest() {
    attempts++;
    return makeRequest().catch(error => {
      console.error(`Attempt ${attempts} failed: ${error}`);
      if (attempts < maxAttempts) {
        console.log('Retrying...');
        return tryRequest();
      } else {
        throw new Error(`Max attempts reached (${maxAttempts})`);
      }
    });
  }

  return tryRequest();
}

retryRequest(3)
  .then(result => console.log(result))
  .catch(error => console.error(error));

在上面的例子中,我们定义了一个makeRequest函数来模拟一个异步请求。这个函数返回一个Promise对象,模拟了请求成功和失败的情况。

然后,我们定义了retryRequest函数来尝试多次请求。这个函数接收一个参数maxAttempts表示最大尝试次数。在tryRequest函数中,我们使用递归调用makeRequest函数,并在请求失败时进行错误处理。

如果请求失败且尝试次数小于最大尝试次数,我们会打印错误信息并进行重试。重试的方式是通过返回tryRequest()来实现的,这样就形成了链式调用。如果尝试次数达到最大尝试次数,则抛出一个错误。

最后,我们调用retryRequest(3)来开始链式调用。在then 方法中,打印出了请求成功的结果;在catch方法中,打印出了最终的错误信息。

通过使用Promise链式调用和递归调用,在请求失败时可以进行重试,并且可以控制最大尝试次数。这样可以实现在失败后继续请求,但达到一定次数后不再请求的逻辑。

总结

  1. then方法必定会返回一个新的Promise

    可理解为后续处理也是一个任务

  2. 新任务的状态取决于后续处理:

    • 若没有相关的后续处理,新任务的状态和前任务一致,数据为前任务的数据

    • 若有后续处理但还未执行,新任务挂起。

    • 若后续处理执行了,则根据后续处理的情况确定新任务的状态

      • 后续处理执行无错,新任务的状态为完成,数据为后续处理的返回值
      • 后续处理执行有错,新任务的状态为失败,数据为异常对象
      • 后续执行后返回的是一个任务对象,新任务的状态和数据与该任务对象一致
相关推荐
冰暮流星7 分钟前
css之动画
前端·css
jump68031 分钟前
axios
前端
spionbo34 分钟前
前端解构赋值避坑指南基础到高阶深度解析技巧
前端
用户40993225021238 分钟前
Vue响应式声明的API差异、底层原理与常见陷阱你都搞懂了吗
前端·ai编程·trae
开发者小天41 分钟前
React中的componentWillUnmount 使用
前端·javascript·vue.js·react.js
永远的个初学者1 小时前
图片优化 上传图片压缩 npm包支持vue(react)框架开源插件 支持在线与本地
前端·vue.js·react.js
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ1 小时前
npm i / npm install 卡死不动解决方法
前端·npm·node.js
Kratzdisteln1 小时前
【Cursor _RubicsCube Diary 1】Node.js;npm;Vite
前端·npm·node.js
杰克尼2 小时前
vue_day04
前端·javascript·vue.js
明远湖之鱼2 小时前
浅入理解跨端渲染:从零实现 React DSL 跨端渲染机制
前端·react native·react.js