Array#map() 中的异步/等待

IT技术 javascript async-await ecmascript-2017
2021-03-07 08:21:14

我收到此代码的编译时错误:

const someFunction = async (myArray) => {
    return myArray.map(myValue => {
        return {
            id: "my_id",
            myValue: await service.getByValue(myValue);
        }
    });
};

错误信息是:

await 是一个保留字

为什么我不能像这样使用它?

我也尝试了另一种方式,但它给了我同样的错误:

 const someFunction = async (myArray) => {
    return myArray.map(myValue => {
        const myNewValue = await service.getByValue(myValue);
        return {
            id: "my_id",
            myValue: myNewValue 
        }
    });
};
5个回答

你不能像你想象的那样做,因为await如果它不是直接在async函数内部,你就不能使用

在这里做的明智的事情是将函数传递给map异步。这意味着map将返回一组Promise。然后我们可以使用Promise.all来在所有 Promise 返回时获取结果。由于Promise.all本身返回一个Promise,外部函数不需要是async

const someFunction = (myArray) => {
    const promises = myArray.map(async (myValue) => {
        return {
            id: "my_id",
            myValue: await service.getByValue(myValue)
        }
    });
    return Promise.all(promises);
}
@stackdave 可能,但在 旁边的差异将无关紧要service.getByValue,这很可能涉及网络调用...
2021-04-20 08:21:14
@lonesomeday 这可以处理调用之间的错误或限制/延迟吗?
2021-04-24 08:21:14
@KylePennell 是的。在从外部函数返回之前,您需要使用try..catch异步函数中的 a 或catch处理程序来处理错误可以return在异步函数之前引入节流阀
2021-04-27 08:21:14
谢谢我已经开始使用它了,反正可读性比速度好,因为大多数 ES6 异步技术总是会更慢,但谁在乎
2021-04-28 08:21:14
在这种情况下,promise 数组对于 let in array 来说不是经典的慢吗?
2021-05-03 08:21:14

如果要使用异步映射函数运行 map,可以使用以下代码:

const resultArray = await Promise.all(inputArray.map(async (i) => someAsyncFunction(i)));

怎么运行的:

  • inputArray.map(async ...)返回一组 Promise - 中的每个值一个inputArray
  • Promise.all()Promise将其转换的阵列周围成一个单一的Promise。
  • 来自单个PromisePromise.all()返回一组值 - 每个Promise都解析为一个值。
  • 我们放置await在前面Promise.all()以便我们等待组合Promise解析并将已解析的子Promise数组存储到变量中resultArray

最后,我们resultArray为 中的每个项目获得一个输出值,inputArray通过函数映射someAsyncFunction在结果可用之前,我们必须等待所有异步函数解析。

那是因为 in 函数map不是async,所以它的 return 语句中不能有await它通过以下修改进行编译:

const someFunction = async (myArray) => {
    return myArray.map(async (myValue) => { // <-- note the `async` on this line
        return {
            id: "my_id",
            myValue: await service.getByValue(myValue)
        }
    });
};

在 Babel REPL 中尝试一下

所以……在没有看到应用程序的其余部分的情况下不可能给出推荐,但是根据您要做什么,要么使内部函数异步,要么尝试为这个块提出一些不同的架构。

更新:有一天我们可能会获得顶级等待:https : //github.com/MylesBorins/proposal-top-level-await

它只返回 ES6 Promise
2021-04-24 08:21:14
谢谢,赞成,但是您的代码返回带有空对象的数组(即[{}, {}])。我想我需要包含某个地方await,但不知道在哪里
2021-04-29 08:21:14
是什么的service.getByValue样子功能怎么样?
2021-05-11 08:21:14
在我看来,OP 期望一组 id'ed 对象作为最终结果,因此与此保持一致,我认为您可能想要return await Promise.all(myArray.map......为了等效。
2021-05-14 08:21:14

这将是 2 个指令,但只需用额外的指令移动“等待”

let results = array.map((e) => fetch('....'))
results  = await Promise.all(results)

我尝试了所有这些答案,但没有一个适合我的情况,因为所有答案都返回一个promise不是result of the promise这样对象

{
  [[Prototype]]: Promise
  [[PromiseState]]: "fulfilled"
  [[PromiseResult]]: Array(3)
  0: ...an object data here...
  1: ...an object data here...
  2: ...an object data here...
  length: 3
  [[Prototype]]: Array(0)
}

然后我找到了这个答案https://stackoverflow.com/a/64978715/8339172指出map函数是否异步或Promise感知。因此,我没有使用await内部map函数,而是使用for循环和await单个项目,因为他说for循环是有async意识的并且会暂停循环。