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. 新任务的状态取决于后续处理:

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

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

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

      • 后续处理执行无错,新任务的状态为完成,数据为后续处理的返回值
      • 后续处理执行有错,新任务的状态为失败,数据为异常对象
      • 后续执行后返回的是一个任务对象,新任务的状态和数据与该任务对象一致
相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax