为何在flatMap中使用async函数无法返回扁平化数组?
为什么async函数结合flatMap无法返回扁平化数组?
核心原因很简单:async函数的返回值永远是Promise,这直接改变了flatMap的输出结构。
先看你给出的第一个正常例子:
const numbers = [[1], [2], [3]]; // typed as number[] const numbersFlatten = await Promise.all( numbers.flatMap((number) => number), );
这里flatMap的回调返回的是number[]类型的数组元素(比如[1]),flatMap会直接把这些数组展开,最终输出一个number[]([1,2,3])。Promise.all接收这个数组后,会把每个非Promise值包装成Promise,最终resolve后得到的还是number[]。
再看添加async后的例子:
const numbers = [[1], [2], [3]]; // typed as number[][] const numbersFlatten = await Promise.all( numbers.flatMap(async (number) => number), );
这里的回调是async函数,哪怕你return的是number[],async函数也会自动把它包装成Promise<number[]>。flatMap此时做的事情是把这些Promise收集起来,输出一个Promise<number[]>[]类型的数组。
当你用Promise.all等待所有Promise完成后,得到的就是每个Promise resolve后的结果——也就是number[]的数组,最终类型自然是number[][],完全没有扁平化效果。
解决方法
如果要实现异步版的flatMap,需要分两步走:先处理异步逻辑,再扁平化结果:
方法1:先map异步操作,再Promise.all + flat
const numbers = [[1], [2], [3]]; const numbersFlatten = (await Promise.all( numbers.map(async (number) => number) )).flat(); // 此时类型为number[]
方法2:封装异步flatMap工具函数
如果需要多次使用,可以自己封装一个异步版本的flatMap:
async function asyncFlatMap<T, U>(arr: T[], callback: (item: T) => Promise<U[]>): Promise<U[]> { // 先执行所有异步操作 const asyncResults = await Promise.all(arr.map(callback)); // 再扁平化结果 return asyncResults.flat(); } // 使用示例 const numbers = [[1], [2], [3]]; const numbersFlatten = await asyncFlatMap(numbers, async (number) => number); // 类型为number[]
内容的提问来源于stack exchange,提问作者maximeSurmontSO
相关产品推荐
相关产品推荐

