Первое: reduce
, вероятно, не лучший инструмент для этого. Похоже, вы просто добавляете записи в массив. reduce
слишком сложен для этой задачи, особенно , если вы делаете что-то асинхронное. Вместо этого конструкция цикла, которую вы можете использовать в функции async
, намного, намного проще.
Я начну с reduce
, затем go с конструкции цикла.
reduce
работает синхронно . Если вы передадите функцию async
в качестве ее обратного вызова, обещание, которое возвращает функция, будет значением аккумулятора, увиденным при следующем обратном вызове. Таким образом, если один из шагов в операции сокращения должен быть асинхронным и возвращать обещание, каждый шаг после того, как он должен быть асинхронным, возвращает обещание (для простоты лучше сделать так, чтобы каждый шаг возвращал обещание ); и результат reduce
будет обещанием конечного значения, а не самого конечного значения. Вы не можете сделать асинхронный вызов синхронным и не можете заставить синхронную операцию (reduce
) ожидать асинхронного результата.
Итак, все ваши обратные вызовы будут иметь дело с обещаниями. Это будет выглядеть примерно так:
const result = await records.reduce(async(arrayPromise, currentValue) => {
// −−−−−−−−−−−−^^^^^−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^
const array = await arrayPromise // <=====
// do stuff
someValue = await asyncCall(currentValue)
array.push(someValue) // <==== `push` rather than `add`, presumably
return array
}, Promise.resolve([]))
// ^^^^^^^^^^^^^^^^−−^
Конечно, поскольку здесь используется await
, оно должно быть в функции async
. В противном случае:
records.reduce(async(arrayPromise, currentValue) => {
const array = await arrayPromise // <=====
// do stuff
someValue = await asyncCall(currentValue)
array.push(someValue)
return array
}, Promise.resolve([]))
.then(result => {
// ...use `result` here
})
.catch(error => {
// ...handle/report error here...
})
Вам лучше использовать циклическую конструкцию, которая изначально поддерживает участие в функции async
:
const result = []
for (const currentValue of records) {
someValue = await asyncCall(currentValue)
result.push(someValue)
}
// ...use `result` here...
или даже
const result = []
for (const currentValue of records) {
result.push(await asyncCall(currentValue))
}
// ...use `result` here...
Если вам нужно сделать это в функции, которая не является функцией async
, вы будете явно иметь дело с обещанием, которое будет выглядеть следующим образом:
(async () => {
const result = []
for (const currentValue of records) {
result.push(await asyncCall(currentValue))
}
return result
})()
.then(result => {
// ...use `result` here
})
.catch(error => {
// ...handle/report error here...
})