У меня есть код ниже, который использует API для получения данных о клиентах. Проблема в том, что когда цикл переходит ко второму индексу, customerIds
сохраняет значение из предыдущего index
(см. журнал консоли ниже).
Кто-нибудь знает, как добиться этого правильно?
Вот мой код
let customerIds = [];
arrayChunks.forEach(async (chunkGroupIds, index) => {
try {
console.info('customerIds - before', index, customerIds)
const checkStatusResult = await checkStatus(
token,
chunkGroupIds
)
chunkGroupIds.map((customerId) => {
const found = checkStatusResult.response.data.find(
(data) => customerId.toString() === data.customerId
)
if (found) {
customerIds = [...customerIds, customerId]
}
})
console.info('customerIds - after', index, customerIds)
} catch (error) {
...
}
})
console.info('customerIds - final', customerIds)
Журналы консоли: О проблеме может свидетельствовать печатаемый текст. Как мы видим, когда он перешел ко второму индексу, он не получил предыдущее значение из первого индекса.
customerIds - before 0 []
customerIds - after 0 [2,3,5]
customerIds - before 1 []
customerIds - after 1 []
... and so on
customerIds - final []
customerIds
должно быть правильным после цикла. (нужно дождаться завершения)
где объявлено customerIds
?
да я изначально думал, что ты кэшируешь customerIds
, перечитал и это не так. (поэтому я удаляю комментарий для использования push
)
Используйте цикл for of
вместо обратного вызова
let customerIds = [];
let index = 0;
for (const chunkGroupIds of arrayChunks) {
try {
console.info('customerIds - before', index, customerIds)
const checkStatusResult = await checkStatus(
token,
chunkGroupIds
)
chunkGroupIds.map((customerId) => {
const found = checkStatusResult.response.data.find(
(data) => customerId.toString() === data.customerId
)
if (found) {
customerIds.push(customerId);
}
})
console.info('customerIds - after', index, customerIds)
} catch (error) {
...
} finally {
index++;
}
}
console.info('customerIds - final', customerIds)
теперь он отображает правильные значения .. я думаю, что это работает. У вас есть идеи, почему мой код выше не работал. или, может быть, это потому, что внутри функции async
есть forEach
, которую я использовал. Однако, если я удалю async
, я получу ошибку машинописного текста.
Да, предыдущий не работал из-за реализации обратного вызова. For each
метод возвращает обратный вызов для каждой итерации элемента массива, и каждый обратный вызов имеет свой собственный контекст выполнения, вы не можете использовать async await
для ожидания завершения первой итерации, если у вас есть код async
внутри обратного вызова. Каждая итерация выполняется независимо от другой.
Это похоже на проблему асинхронности, может показаться, что промисы в массиве выполняются последовательно, но это не так. В цикле forEach
все они выполняются одновременно.
Это может быть что-то хорошее в вашем случае, так как вам не нужно ждать суммы последовательного времени, где вы, вероятно, боретесь, находится в последней части, где вы хотите увидеть окончательный массив со всеми добавленными значениями, для этого Я рекомендую следующее:
const promises = arrayChunks.map(async (chunkGroupIds, index) => {
try {
console.info('customerIds - before', index, customerIds)
const checkStatusResult = await checkStatus(
token,
chunkGroupIds
)
chunkGroupIds.map((customerId) => {
const found = checkStatusResult.response.data.find(
(data) => customerId.toString() === data.customerId
)
if (found) {
customerIds = [...customerIds, customerId]
}
})
console.info('customerIds - after', index, customerIds)
} catch (error) {
...
}
})
await Promise.all(promises); // Wait until all of them are finished
console.info('customerIds - final', customerIds)
Здесь утилита Promise.all
позволяет дождаться окончания сбора промисов, функции автоматически сопоставляются с промисами благодаря ключевому слову async
.
Если вам нужно, чтобы ваши обещания выполнялись последовательно, вы можете использовать подход, рекомендованный @amir-saleem. В противном случае мое предложение было бы лучше с точки зрения производительности.
я получил ошибку машинописного текста Никакая перегрузка не соответствует этому вызову. Перегрузка 1 из 2, '(значения: только для чтения unknown[] | []): Promise<[] | unknown[]>', выдало следующую ошибку.
Эта ошибка, похоже, не связана с кодом, который вы разместили изначально, можете ли вы предоставить больше контекста?
@appleapple я изначально использовал
push
, но это не сработало.