axios allSettled -设置时间延迟以避免API滥用率限制

pn9klfpd  于 2023-11-18  发布在  iOS
关注(0)|答案(3)|浏览(178)

我正在使用Promise.allSettled对Github API的几百个请求进行多次获取。我被阻塞了,因为它们都被同时调用,所以我想在每个请求之间添加5毫秒的延迟。这可以使用Promise.allSettled吗?

zbsbpyhn

zbsbpyhn1#

allSettled既不会帮助你,也不会阻碍你;它在时间方面没有任何逻辑,除了等待promise解决。它将由你来创建你的promise,以便它们具有你想要的延迟。
举例来说:

const delay = (milliseconds) => new Promise(resolve => setTimeout(resolve, milliseconds);

const urls = ['www.foo.com/whatever', /* etc for a few hundred urls */];
const promises = urls.map((url, index) => {
  return delay(index * 5)
    .then(() => fetch(url))
})

Promise.allSettled(promises)
  .then(results => {
    // do whatever with the results
  });

字符串

o75abkj4

o75abkj42#

可能你需要的是并发限制,而不是延迟。

const urls = [
  "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=3s&foo1",
  "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=3s&foo2",
  "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=3s&foo3",
  "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=3s&foo4",
  "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=3s&foo5",
  "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=3s&foo6",
  "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=3s&foo7"
];

function fetchBottleneck(concurrency = 1) {
  const queue = [];
  let pending = 0;
  return async (...args) => {
    if (pending === concurrency) {
      await new Promise((resolve) => queue.push(resolve));
    }

    pending++;

    return fetch(...args).then((value) => {
      pending--;
      queue.length && queue.shift()();
      return value;
    });
  };
}

// Use fetch queue
(async () => {
  const fetchInQueue = fetchBottleneck(3);
//No matter how many times you call the 'fetchInQueue' method, you get a maximum of 3 pending requests at the same time.

  const results = await Promise.all(
    urls.map(async (url) => {
      try {
        const response = await fetchInQueue(url);
        console.log(`Got response for ${url}`);
        return { status: "fulfilled", value: await response.json() };
      } catch (reason) {
        return { status: "rejected", reason };
      }
    })
  );

  console.log("Done:", JSON.stringify(results));
})();

字符串
更好的解决方案是使用多个第三方库提供的并发限制(例如http://bluebirdjs.com/docs/api/promise.map.html
Live browser example

import CPromise from "c-promise2";

CPromise.allSettled(
  [
    "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=3s&foo1",
    "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=4s&foo2",
    "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=2s&foo3",
    "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=3s&foo4",
    "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=4s&foo5",
    "https://fake.url.to.test/",
    "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=3s&foo6",
    "https://run.mocky.io/v3/40594989-00c2-4798-94da-c4a9ab251558?mocky-delay=3s&foo7"
  ],
  {
    mapper: (url) => {
      console.log(`request [${url}]`);
      return fetch(url).then((response) => response.json());
    },
    concurrency: 2
  }
).then((results) => {
  console.log(`Done: `, JSON.stringify(results));
});

ssgvzors

ssgvzors3#

这个版本的Promise.allSettled使用了上面定义的delay方法,但是在调用之间添加了一个随机延迟,它可以选择过滤fulfilledrejected Promise状态:

function allSettledDelayed(promises = [], milliseconds = 100, status = '') {
  return new Promise(async(resolve, reject) => {
    const delay = (milliseconds) => new Promise(resolve => setTimeout(resolve, milliseconds));
    try {
        let randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
        promises = promises.map((promise, index) => delay(randomInt(0, (index+1) * milliseconds)).then(() => promise));
      var responses = await Promise.allSettled(promises);
      if (status == "fulfilled" || status == "rejected") responses = responses.filter(p => p.status === status).map(p => p.value);
      return resolve(responses);
    } catch (error) {
      return reject(error);
    }
  });
} //allSettledDelayed

(async() => {
  var urls = Array(10).fill().map((v, i) => `https://httpbin.org/response-headers?key=${i}`);
  const promises = urls.map(url => fetch(url).then((response) => response.status))
  var res = await allSettledDelayed(promises, 300, '')
  console.log(res)
})();

字符串

相关问题