Как задать задержку для fetch при скачивании более 4000 фото?

библиотека node-fetch
// items.length - 5000
items.map(el => download(el))

async function download(url) {
    const response = await fetch(url);
    if(response.status === 200) {
        const buffer = await response.buffer();
....

Файлы начинают качаться все сразу даже канал забивается.
Во время скачивания ресурс блочит и приходится перезапускать скрипт
Как добавить задержку, чтобы допустим фетч запускался каждые 500 милисекунд
  • Вопрос задан
  • 620 просмотров
Решения вопроса 3
sergiks
@sergiks Куратор тега JavaScript
♬♬
Можно в N параллельных «потоков» скачивать. В каждом случайная пауза перед очередным URL:
const N = 3;

const delay = ms => new Promise(res => setTimeout(res, ms));

const next = () => {
  if (items.length > 0) {
    return download(items.shift())
      .then(delay(500 + Math.floor(Math.random() * 500))) // случайная пауза между закачками
      .then(next);
  }
};

const works = Array.from({ length: N }, () =>
  Promise.resolve()
    .then(next)
    .catch(console.error)
);

Promise.all(works).then(() => console.log('All Done'));
Ответ написан
RAX7
@RAX7
Помимо случайной задержки нужно еще ограничить количество одновременных запросов, примерно так:
function randomDelay(min = 250, max = 750) {
  return new Promise((resolve) => {
    const ms = Math.random() * (max - min) + min;
    setTimeout(resolve, ms);
  });
}

function downloadAll(urls, limit = 4) {
  return new Promise((resolveAll, rejectAll) => {
    const result = [];
    const iter = urls.entries();
    let fulfilled = 0;

    const next = () => {
      const { done, value } = iter.next();

      if (done) {
        if (fulfilled === urls.length) {
          resolveAll(result);
          return;
        }

        return;
      }

      const [index, url] = value;
      const onFulfilled = (val) => {
        result[index] = val;
        fulfilled += 1;
        next();
      };

      randomDelay()
        .then(() => fetch(url))
        .then(onFulfilled, rejectAll);
    };

    for (let i = 0, l = Math.min(limit, urls.length); i < l; i++) {
      next();
    }
  });
}

const urls = Array.from(
  { length: 100 },
  (_, i) => `https://jsonplaceholder.typicode.com/todos/${i + 1}`
);

(async () => {
  const responses = await downloadAll(urls, 2);
  const data = await Promise.all(responses.map((r) => r.json()));
  console.log(data);
})();
Ответ написан
MvcBox
@MvcBox
Software Developer [C/C++/JS(for Node.js)/etc]
'use strict';

const Bluebird = require('bluebird');

/* Тут какой-то Ваш код */

Bluebird.map(items, async function(url) {
  try {
    const response = await fetch(url);

    if (response.status === 200) {
        const buffer = await response.buffer();
        /* Что-то делаете с буффером */
    }

    await Bluebird.delay(1000); // Можно добавить задержку после каждого успешного запроса
  } catch(err) {
    console.error(err);
  }
}, {
  concurrency: 3 // Указываете во сколько потоков выполнять запросы
}).catch(console.error);
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
yarkov
@yarkov Куратор тега JavaScript
Помог ответ? Отметь решением.
Задача разовая? Если так, то я бы сформировал файл с урлами и скормил его wget например.
Ответ написан
@KingstonKMS
Используйте for или даже while циклы.
do {
const item = items.shift();
await download(item);
/* 
Здесь реализовать асинхронный таймаут
*/
} 
while (items.length >0);
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы