У меня есть функция карты, которая должна извлекать данные из онлайн-источника. Проблема в том, что 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.. :(
есть две проблемы, которые я не могу понять:
map(), кажется, выполняет свою работу параллельно (правда ли это?), что мне здесь не нужно, потому что, как я уже сказал, мне нужно, чтобы он работал предпочтительно один за другим каждую секунду
моя функция сна вообще не работает. в логе консоли просто каша и все сразу
каким будет правильный способ заставить это работать раз в секунду? и можно ли снова использовать запасной вариант (просто запустив «getAddress»)?
большое спасибо!
установить время ожидания () — это функция, которая работает ОДНАЖДЫ, с задержкой на указанное вами время. С другой стороны, установитьинтервал() — это функция, которая выполняет все, что находится внутри, в бесконечном цикле каждую секунду (или каждый раз, когда вы указали).
Вы можете проверить документы здесь: установить время ожидания () и установитьинтервал()
Что бы я сделал, так это обернул функцию, которая извлекается из API, внутри установитьинтервал(), примерно так:
setInterval(() => {
your code here
}, 1000);
И вы можете изменить эти 1000 (1000 мс или 1 с) в любое время.
Чтобы ответить на ваш вопрос:
map
не ждет завершения обещания, чтобы перейти к следующей операции, но это можно исправить с помощью цикла for
.Вы можете использовать цикл 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) => {
есть идеи, в чем может быть проблема?