Как запускать функцию карты (асинхронную, выборку, обещание) каждую секунду одну за другой, а не параллельно?

У меня есть функция карты, которая должна извлекать данные из онлайн-источника. Проблема в том, что API позволяет получать данные только один раз в секунду. поэтому я попытался сделать это так:

const sleep = (ms: number) => {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
};

const promises = projectData.map(async (project, index) => {
        return await getAddress(asdf)
          .then((nominatimData) => {
        // ....do something...
          })
          .catch(async (e) => {
            console.info("failed", e);
            return await sleep(2000).then(() => {
              console.info("another try... ")
              return getAddress(asdf);
            });
          });
    });

    await Promise.allSettled(promises);

    console.info("Project Data", projectData); //does still fire before all getAddress() are present.. :(

есть две проблемы, которые я не могу понять:

  1. map(), кажется, выполняет свою работу параллельно (правда ли это?), что мне здесь не нужно, потому что, как я уже сказал, мне нужно, чтобы он работал предпочтительно один за другим каждую секунду

  2. моя функция сна вообще не работает. в логе консоли просто каша и все сразу

каким будет правильный способ заставить это работать раз в секунду? и можно ли снова использовать запасной вариант (просто запустив «getAddress»)?

большое спасибо!

Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
1
0
29
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

установить время ожидания () — это функция, которая работает ОДНАЖДЫ, с задержкой на указанное вами время. С другой стороны, установитьинтервал() — это функция, которая выполняет все, что находится внутри, в бесконечном цикле каждую секунду (или каждый раз, когда вы указали).

Вы можете проверить документы здесь: установить время ожидания () и установитьинтервал()

Что бы я сделал, так это обернул функцию, которая извлекается из API, внутри установитьинтервал(), примерно так:

setInterval(() => {    
  your code here
}, 1000);

И вы можете изменить эти 1000 (1000 мс или 1 с) в любое время.

Ответ принят как подходящий

Чтобы ответить на ваш вопрос:

  1. Да, map не ждет завершения обещания, чтобы перейти к следующей операции, но это можно исправить с помощью цикла for.
  2. Поскольку вы запускаете операции с картой, ваша функция сна запускается для каждого элемента в массиве одновременно параллельно, логика хороша, а не метод

Вы можете использовать цикл for, который разрешает асинхронные/ожидающие операции, хотя, поскольку ваша цель — дождаться ответа от сервера, я бы порекомендовал вместо этого собственный цикл курсора.

let cursor = 0;
const timeout = 1000;
const sleep = (ms) => {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
};

const loop = async () => {
    // Break if index is out of bounds
    if (!projectData[cursor]) {
        return console.info('Done');
    }

    await getAddress(projectData[cursor]).then((nominatimData) => {
        // ....do something...
        // Proceed to the next element in the array
        cursor++;
        await loop();

    }).catch(async (e) => {
        console.info(`Failed, retrying in ${ timeout }ms`);
        await sleep(timeout);
        await loop(); // Retry the loop with the same cursor index
    });
};
await loop();

Привет, большое спасибо за ваш ответ! это кажется решением моей проблемы, НО: он сразу же переходит к улову, кажется, что он даже не пытается выполнить функцию getAddress. что странно :/. мне пришлось сделать функцию nominationData асинхронной: .then(async (nominatimData) => { есть идеи, в чем может быть проблема?

Hannes F 06.05.2022 11:50

простите... глупая ошибка. Ваше решение работает для меня! Большое спасибо

Hannes F 06.05.2022 12:17

Другие вопросы по теме