Estoy tratando de reduce una variedad de métodos asincrónicos y sincrónicos. Tengo dos métodos síncronos y un método asíncrono que da formato básico a un objeto. Dado que tengo una combinación de métodos asincrónicos y sincrónicos, estoy usando async/await con mi reduce . El problema es que mi método formatName devuelve el error Cannot read property 'toUpperCase' of undefined porque el parámetro de person pasado es una promesa. Pensé que dado que uso await en mi reducción, la devolución de llamada debería devolver el valor real en lugar de una promesa:
const results = await fn(finalResult);
Mi código funciona bien si elimino los métodos sincrónicos de mi matriz. Pero necesito reducir una serie de métodos sincrónicos y asincrónicos. ¿Alguien tiene consejos sobre cómo puedo evitar esto? Mi código completo está abajo.
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();Las funciones asíncronas siempre devuelven promesas, por lo que en iteraciones posteriores de la devolución de llamada .reduce , el acumulador será una Promesa que debe esperar para resolver primero.
Mientras que podrías hacer
const accumVal = await finalResult al comienzo de la devolución de llamada, esto sería mucho más simple al evitar reduce por completo en mi opinión.
const process = async () => { let person = initialPerson; for (const fn of formattedStagesWithAsync) { person = await fn(person); }En el caso de que cada una de sus funciones devuelva el objeto original, como en el caso aquí, eso se simplifica a:
const process = async () => { for (const fn of formattedStagesWithAsync) { await fn(initialPerson); } (también está mutando la initialPerson en su código original)
Promise devolver el valor async , pero no uses la opción async y await para Promise , solo return
const promiseHandler = () => { return new Promise((done, reject) => { setTimeout(() => { done("hello"); }); }); } promiseHandler().then(v => { console.log(v); // hello });