我想了解为什么将
.flatMap()
与 async
一起使用不会返回展平数组。
例如,对于 Typescript,这会返回一个数字数组: 我知道
Promisse.all
和async
对于简单的数字数组来说是没有用的,它只是更容易复制
const numbers = [[1], [2], [3]];
// typed as number[]
const numbersFlatten = await Promise.all(
numbers.flatMap((number) => number),
);
对于 Typescript,返回一个数字数组的数组(刚刚添加了一个异步):
const numbers = [[1], [2], [3]];
// typed as number[][]
const numbersFlatten = await Promise.all(
numbers.flatMap(async (number) => number),
);
async
函数都隐式返回 Promises。通过创建 .flatMap()
回调 async
,它现在返回一个解析为数组中的 number
的 Promise。为了让 .flatMap()
正常工作并展平其结果,回调应该返回一个数组,而不是 Promise。以下是有问题的行为的示例:
const numbers = [[1], [2], [3]];
const promiseAllArg = numbers.flatMap(async (number) => number); // same as `.flatMap(number => Promise.resolve(number))`, flatMap doesn't know how to flatten `Promise<number>` into a resulting array
console.log(promiseAllArg); // [Promise<[1]>, Promise<[2]>, Promise<[3]>]
.map()
调用来获取解析值的嵌套数组,然后使用 .flat()
调用:
(async () => {
const numbers = [[1], [2], [3]];
const awaitedNumbers = await Promise.all(
numbers.map(async (number) => number) // some async code
);
const numbersFlattened = awaitedNumbers.flat() // flatten the resolved values
console.log(numbersFlattened);
})();
我想补充一点,事实上
Promise
是 eager 也具有性能影响。
const asyncFlatMap = <A, B>(arr: A[], f: (a: A) => Promise<B>) =>
Promise.all(arr.map(f)).then(arr => arr.flat());
asyncFlatMap([[1], [2], [3]], async nums => nums); // Promise<number[]>
您可以在上面的代码中看到,我们需要
map
,然后 flat
,由于中间存在 then
,因此需要通过微任务队列进行额外的往返。为了玩乐高而进行这种往返是浪费。
请注意,如果您不编写
asyncFlatMap
帮助程序,您当然可以避免 then
。我在这里做一个一般性的声明。
如果你碰巧嵌套了很多 Promise,你可能会对 Fluture 感兴趣。
期货是惰性的,所以你可以在任何东西运行之前用它们玩乐高。
import { resolve, parallel, promise, map } from 'fluture';
import { pipe } from 'fp-ts/function';
const numbersFlatten = await pipe(
numbers.map(nums => resolve(nums)), // Future<number[]>[]
parallel(10), // Future<number[][]>
map(x => x.flat()), // Future<number[]>
promise // Promise<number[]>
);
在上面的代码中,我使用
promise
将 Future 转换回 Promise,以匹配您的用例。只有当调用该函数时才会运行计算。 fork
也将在不涉及承诺的情况下运行计算。
如果您不熟悉
pipe
:第一个参数是通过其余函数参数传递的值。
10
中的神奇值
parallel
只是同时运行的最大计算数量。也可能是其他什么。