JavaScript使用reduce处理混合同步异步函数数组报错如何解决
问题原因
- 所有被
async修饰的函数,返回值永远是Promise实例,和你return的内容无关。你在reduce中传入的回调是async函数,所以每一轮迭代返回的累加器本质都是Promise,而非处理后的person对象。 - 你只对当前执行的
fn做了await,没有对前一轮返回的累加器做await,所以第二轮执行同步方法formatAge时,传入的参数是Promise实例,自然读取不到name、age等属性,触发报错。 - 移除同步方法后所有迭代都是异步逻辑,内部自动处理了Promise解析,所以不会报错。
解决方案
只要在每轮迭代执行处理函数前,先await上一轮的累加器即可。await对同步值没有副作用,也能正常解析Promise实例,完美兼容同步、异步函数混合的场景。
修正后的完整代码如下:
const formatName = (person) => { person.name = person.name.toUpperCase(); return person; } const formatAge = (person) => { person.age += 10; return person; } // Async function const formatLocation = async (person) => { await new Promise(resolve => setTimeout(resolve, 1000)); person.location = `${person.location.toLocaleLowerCase()}` return person; } const initialPerson = { name: "john", age: 35, location: 'USA' } const formattedStagesWithAsync = [ formatLocation, // asynchronous formatAge, // synchronous formatName //synchronous ]; const process = async () => { const formattedPerson = await formattedStagesWithAsync.reduce(async (prevResultPromise, fn) => { // 先解析上一轮的结果,兼容同步、异步返回值 const prevResult = await prevResultPromise; const results = await fn(prevResult); return results; }, initialPerson); console.log(`Formatted person - ${JSON.stringify(formattedPerson, null, 2)}`); } process();
运行后输出结果为:
Formatted person - { "name": "JOHN", "age": 45, "location": "usa" }
内容的提问来源于stack exchange,提问作者John Grayson
相关产品推荐
相关产品推荐

