多个promise并发执行,如果某个promise失败,则尝试重新执行该promise一次,如果还是失败则提示错误

思路

可以使用 Promise.all()和Promise.catch() 结合的方式来实现多个promise的并发执行,并在某个promise失败时尝试重新执行。

首先,将所有的promise放入数组中,并使用Promise.all()来同时执行这些promise,这样可以确保所有的promise都成功执行。

然后,通过catch()方法来捕获拒绝的promise,并在捕获到之后进行重新执行。

代码

const promise1 = () => Promise.resolve(1);
let isFirst = true;
const promise2 = () =>
  new Promise((resolve, reject) => {
    console.log('promise2 isFirst:', isFirst);
    if (isFirst) {
      // 模拟promise第一次执行失败,第二次执行成功
      reject('2 error');
      isFirst = false;
    }
    resolve('2 success');
  });
const promise3 = () => Promise.resolve(3);

const promises = [promise1, promise2, promise3];

Promise.all(
  promises.map(promise => {
    return promise().catch(error => {
      // 如果失败则重新执行该promise
      console.error('Promise failed, retrying...:');
      return promise();
    });
  })
)
  .then(res => {
    console.log('All promises succeeded: ', res);
  })
  .catch(error => console.error('All promises failed'));

打印结果:

多个promise并发执行,如果某个promise失败,则尝试重新执行该promise一次,如果还是失败则提示错误_第1张图片

进一步完善

封装一个wrap函数,统一处理失败后重试的这段逻辑,不需要再放在promise.all里面,这样子提高这些promise的可扩展性。

const wrap = (func) => {
  // 调用wrap函数,会立即执行func
  let last = func();
  // 使用闭包,返回一个函数
  return () =>
    last.catch(() => { 
      // 失败之后,重新执行func,并保存在last,这样可以保证所有promise只会被执行一次
      // 比如某个promise第一次执行失败,重试成功,last将会保存成功后的promise,下次使用到的时候就是返回成功后的这个promise
      last = func();
      return last.catch(() => {
        // will throw error if second failed
        throw new Error('second execute failed');
      });
    });
};

const promise1 = wrap(() => Promise.resolve(1));
let isFirst = true;
const promise2 = wrap(
  () =>
    new Promise((resolve, reject) => {
      console.log('promise2 isFirst:', isFirst);
      if (isFirst) {
        reject('2 error');
        isFirst = false;
      }
      resolve('2 success');
    })
);
const promise3 = wrap(() => Promise.resolve(3));

const promises = [promise1, promise2, promise3];

Promise.all(promises.map(promise => promise()))
  .then(res => {
    console.log('All promises succeeded: ', res);
  })
  .catch(error => console.error('All promises failed'));

打印结果:

多个promise并发执行,如果某个promise失败,则尝试重新执行该promise一次,如果还是失败则提示错误_第2张图片

补充(Promise.allSettled())

官方:Promise.allSettled()
Promise.allSettled来判断多个Promise的执行结果,包括成功和失败。Promise.allSettled返回一个新的Promise对象,该对象在所有给定的Promise已被决议或拒绝后完成,并带有一个对象数组,每个对象表示对应的Promise结果

例子:

const promises = [promise1, promise2, promise3];

Promise.allSettled(promises)
  .then(results => {
    results.forEach((result, index) => {
      if (result.status === 'fulfilled') {
        console.log(`Promise ${index + 1} fulfilled with value:`, result.value);
      } else {
        console.log(`Promise ${index + 1} rejected with reason:`, result.reason);
      }
    });
  });

在上述例子中,promises数组包含多个Promise对象。Promise.allSettled等待所有Promise对象都被决议或拒绝后,返回一个结果数组。结果数组中的每个对象包含了对应Promise的状态和结果。使用forEach循环遍历结果数组,根据状态输出相应的信息。

注意:Promise.allSettled是ES2020中新增的方法,如果需要在较旧的环境中使用该方法,可以使用Promise.all和Promise.catch的组合来实现类似的功能。

该方法是Promise 并发Promise.allSettled()方法之一。当您有多个不依赖于彼此才能成功完成的异步任务,或者您总是想知道每个 Promise 的结果时,通常使用Promise.allSettled()。

相比之下,Promise.all()如果任务相互依赖,或者如果您想在其中任何一个任务拒绝时立即拒绝,则返回的 Promise 可能更合适。

你可能感兴趣的:(实战经验,javascript,前端)