Javascript - 将异步回调传递给 Array.reduce()

Bob*_*ole 3 javascript reduce asynchronous async-await

我正在开发一个使用 Array.reduce 的函数,并且需要在 reduce 函数内添加异步 API 调用。这要求我对传入的回调使用异步函数reduce,因为我await在函数内部使用它来等待异步 API 调用。

我在正确编写归约时遇到一些问题。这是目前的情况(工作):

const result = records.reduce((array, currValue) => {
    //do stuff
    return array
}, [])
Run Code Online (Sandbox Code Playgroud)

这是我尝试将其更改为:

const result = records.reduce(async(array, currentValue) => {
    // do stuff
    someValue = await asyncCall(currentValue)
    array.add(someValue)
    return array
}, [])
Run Code Online (Sandbox Code Playgroud)

我收到的错误是“没有与此调用匹配的重载”。

这对我来说似乎很有意义,因为reduce接受返回数组的回调,而异步函数返回回调,而不是数组。但是当我阅读如何将异步函数传递到 .reduce 的其他示例时,它们似乎都只是将异步函数传递到 reduce 中,没有任何问题。

以下是我查看的几个链接:

https://advancedweb.hu/how-to-use-async-functions-with-array-reduce-in-javascript/

JavaScript 数组 .reduce 与 async/await

https://gyandeeps.com/array-reduce-async-await/

当我将归约函数声明为异步时,我得到了不匹配重载错误,这对我来说是有意义的。我不确定这对其他人来说是否有效。

T.J*_*der 5

首先:reduce可能不是为此使用的最佳工具。看起来您只是将条目添加到数组中。reduce对于该任务来说过于复杂,特别是如果您正在执行异步操作。相反,可以在async函数中使用的循环结构要简单得多。

\n\n

我将从 开始reduce,然后转到循环构造。

\n\n

reduce同步工作。如果您传递一个async函数作为其回调,则该函数返回的承诺将是下一个回调看到的累加器值。因此,如果reduce操作中的一个步骤需要异步并返回一个promise,那么它之后的一步都必须异步返回一个promise(为了简单起见,最好只让每一步都返回一个promise);will 的结果reduce是对最终值的承诺,而不是最终值本身。您无法使异步调用同步,也无法使同步操作 ( reduce) 等待异步结果。

\n\n

因此,您的所有回调都将处理承诺。它看起来有点像这样:

\n\n
const result = await records.reduce(async(arrayPromise, currentValue) => {\n// \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92^^^^^\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92^^^^^^^^^^^^\n    const array = await arrayPromise // <=====\n    // do stuff\n    someValue = await asyncCall(currentValue)\n    array.push(someValue) // <==== `push` rather than `add`, presumably\n    return array\n}, Promise.resolve([]))\n// ^^^^^^^^^^^^^^^^\xe2\x88\x92\xe2\x88\x92^\n
Run Code Online (Sandbox Code Playgroud)\n\n

当然,既然使用了await,它就必须在一个async函数中。否则:

\n\n
records.reduce(async(arrayPromise, currentValue) => {\n    const array = await arrayPromise // <=====\n    // do stuff\n    someValue = await asyncCall(currentValue)\n    array.push(someValue)\n    return array\n}, Promise.resolve([]))\n.then(result => {\n    // ...use `result` here\n})\n.catch(error => {\n    // ...handle/report error here...\n})\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

您最好使用本身支持成为async函数一部分的循环构造:

\n\n
const result = []\nfor (const currentValue of records) {\n    someValue = await asyncCall(currentValue)\n    result.push(someValue)\n}\n// ...use `result` here...\n
Run Code Online (Sandbox Code Playgroud)\n\n

甚至

\n\n
const result = []\nfor (const currentValue of records) {\n    result.push(await asyncCall(currentValue))\n}\n// ...use `result` here...\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果您需要在不是async函数的函数中执行此操作,您将显式处理 Promise,如下所示:

\n\n
(async () => {\n    const result = []\n    for (const currentValue of records) {\n        result.push(await asyncCall(currentValue))\n    }\n    return result\n})()\n.then(result => {\n    // ...use `result` here\n})\n.catch(error => {\n    // ...handle/report error here...\n})\n
Run Code Online (Sandbox Code Playgroud)\n