Избегайте использования await в цикле for, когда результат Promise обновляет саму переменную цикла итерации.
Есть ли способ не использовать внутренний цикл ожидания для следующего кода?
const redirects = ['redirectId1'];
for (let i = 0; i < redirects.length; i++) {
const promiseResult = await anAsyncFunction(redirects[i]);
if (promiseResult.redirects) {
redirects.forEach(newRedirect => {
if (!redirects.includes(newRedirect)) redirects.push(newRedirect);
});
}
}
Я пробовал использовать карту
const redirects = ['redirectId1'];
const promiseArr = redirects.map(async redirect => {
const promiseResult = await anAsyncFunction(redirect);
if (promiseResult.redirects) {
redirects.forEach(newRedirect => {
if (!redirects.includes(newRedirect)) redirects.push(newRedirect);
});
}
});
await Promise.all(promiseArr);
но при этом код выполняется дальше, прежде чем
newRedirect
помещается в массив перенаправлений, поэтому не вызывает
anAsyncFunction
для новой добавленной стоимости.
Я хочу знать, есть ли какой-нибудь способ добиться этого?
2 ответа
Если идея состоит в том, чтобы отправлять каждый запрос как можно скорее, не дожидаясь разрешения более ранних запросов, вы можете использовать рекурсивную асинхронную функцию, которая вызывает себя, когда результат содержит перенаправления:
const recurse = (redirects) => Promise.all(
redirects.map(r => anAsyncFunction(r)
.then(({ redirects }) => {
if (redirects) {
return recurse(redirects);
}
})
)
);
// pass in the initial array:
await recurse(redirects);
Если вам также нужно использовать заполненный внешний
redirects
массив позже, тогда:
const recurse = (redirects) => Promise.all(
redirects.map(r => anAsyncFunction(r)
.then(({ redirects }) => {
return redirects
? recurse(redirects).then(res => [redirects, res])
: [];
})
)
);
// pass in the initial array:
const allRedirects = [initialRedirects, await recurse(initialRedirects)].flat(Infinity);
Если вы заинтересованы в том, чтобы каждый пакет перенаправления работал параллельно и продолжал запрашивать дополнительные перенаправления, пока они есть, вы можете добиться этого следующим образом:
const handleRedirects = async (_redirects) => {
const newRedirects = [];
await Promise.all(
_redirects.map(async (redirect) => {
const promiseResult = await anAsyncFunction(redirect);
if (promiseResult.redirects) {
promiseResult.redirects.forEach((newRedirect) => {
if (!_redirects.includes(newRedirect)) newRedirects.push(newRedirect);
});
}
})
);
return newRedirects;
};
const run = async () => {
const redirects = ['redirectId1'];
let newRedirects = [ ...redirects ];
do {
newRedirects = await handleRedirects(newRedirects);
redirects.push(...newRedirects);
} while (newRedirects.length)
}