aurora-article icon indicating copy to clipboard operation
aurora-article copied to clipboard

Promise 的一些简单处理

Open starryiu opened this issue 2 years ago • 0 comments

关于 Promise 的一些异步操作整理,包括 同时获取、顺序获取、获取最快的promise、超时处理等。

模拟请求数据

const getData = (message, time = 1000, type = "resolve") => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (type === "resolve") {
        resolve({ statusCode: 200, message });
      } else {
        reject({ statusCode: 400, message });
      }
    }, time);
  });
};

获取非异步值的promise

const resolveFunc = async () => {
  const promise = Promise.resolve(123);
  const res = await promise;
};
resolveFunc();

同时获取

const AllGet = async () => {
  //Promise.allSettled同时获取,返回的Promise都将被兑现,而Promise.all中存在拒绝的promise则会报错,catch会捕获第一个拒绝的promise的值
  const results = await Promise.allSettled(
    Array.from({ length: 6 }).map((value, index) => {
      if (index === 2 || index === 5) {
        return getData(index, 1000, "reject");
      } else {
        return getData(index);
      }
    })
  );
};
AllGet();

顺序获取

//需要将promise写成函数返回的格式,不写成函数reduce中是不会进行等待的
//顺序获取往往是下一个promise需要上一个的结果作为参数,写成函数用以传递参数
const SequenceGet = async () => {
  Array.from({ length: 6 }).reduce(async (promiseChain) => {
    const res = await promiseChain;
    return getData(res.message + 10);
  }, getData(1));
};
SequenceGet();

如果使用reduce方式难以理解,也可以使用for循环的方式,但是不要用数组的forEach函数,forEach函数是不会等待异步的。

  const arr = Array.from({ length: 6 }, (_, index) => (prevData) => {
    return getData(prevData === null ? index + 1 : index + 1 + prevData);
  });
  let prevData = null;
  for (let promise of arr) {
    let nowData = await promise(prevData);
    prevData = nowData;
    console.log(nowData);
  }

从promise数组中获取一个最快的promise

使用 Promise.race

//从promise数组中获取一个最快的promise
const receFunc = async () => {
  //常用做请求超时重试请求或报错
  const res = await Promise.race([
    getData(1, 1000),
    getData(3, 500, "reject"),
    getData(2, 2000),
  ]).catch((err) => console.log(err));
};
receFunc();

使用 Promise.any,比较新的方法,相较于 Promise.race 更符合日常使用场景。

const anyFunc = async () => {
  //和race的区别是获取到的promise必须是成功的
  const res = await Promise.any([
    getData(1, 1000),
    getData(2, 2000),
    getData(3, 500, "reject"),
  ]);
};
anyFunc();

重复请求,三次都失败才放弃,且每次请求时间不能超过2s

function retryGet() {
  let retryNumber = 0;
  return function _retry() {
    //只重试三次
    retryNumber++;
    //模拟数据,第三次为成功,前两次都是失败
    let promises = [];
    if (retryNumber === 3) {
      promises = [getData(1, 1000), getData(0, 2000, "reject")];
    } else if (retryNumber < 3) {
      promises = [getData(0, 1000, "reject"), getData(0, 2000, "reject")];
    } else if (retryNumber > 3) {
      retryNumber = 0;
      return Promise.resolve({ statusCode: 400, message: 0 });
    }
    return new Promise((resolve, reject) => {
      Promise.race(promises)
        .then((res) => {
          retryNumber = 0;
          resolve(res);
        })
        .catch((err) => reject(err));
    }).catch((err) => {
      return _retry();
    });
  };
}
async function test() {
  const data = await retryGet()();
  console.log(data);
}
test();

starryiu avatar Aug 02 '23 04:08 starryiu