javascript - 减少异步和同步函数的数组

javascript - reduce array of async and sync functions

我正在尝试 reduce 异步和同步方法的数组。我有两种同步方法和一种异步方法,它们对对象进行一些基本格式化。由于我混合使用了异步和同步方法,因此我将 async/await 与我的 reduce 一起使用。问题是我的 formatName 方法 return 错误 Cannot read property 'toUpperCase' of undefined 因为传入的 person 参数是一个承诺。我认为由于我在我的 reduce 中使用 await,回调应该 return 实际值而不是承诺:

const results = await fn(finalResult);

如果我从我的数组中取出同步方法,我的代码工作正常。但是我需要减少同步和异步方法的数组。有没有人有关于如何解决这个问题的提示?我的完整代码如下。

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 (finalResult, fn) => {
        const results = await fn(finalResult);
        return results;
      }, initialPerson);

    console.log(`Formatted person - ${JSON.stringify(formattedPerson, null, 2)}`);
}   

process();

异步函数总是 return 承诺,因此在 .reduce 回调的后续迭代中,累加器将是一个承诺,您需要先等待解决。

虽然你可以做到

const accumVal = await finalResult

在回调开始时,完全避免 reduce IMO 会简单很多。

const process = async () => {
  let person = initialPerson;
  for (const fn of formattedStagesWithAsync) {
    person = await fn(person);
  }

如果您的每个函数 return 都是原始对象,就像这里的情况一样,可以简化为:

const process = async () => {
  for (const fn of formattedStagesWithAsync) {
    await fn(initialPerson);
  }

(您也在改变原始代码中的 initialPerson

Promise return async 值但不要为 Promise 使用 asyncawait 选项,只需 return

Promise docs

const promiseHandler = () => {
    return new Promise((done, reject) => {
        setTimeout(() => {
            done("hello");
        });
    });
}

promiseHandler().then(v => {
    console.log(v); // hello
});