Bienvenido a
Recibo un error de tiempo de compilación en este código:
const someFunction = async (myArray) => {
return myArray.map(myValue => {
return {
id: "my_id",
myValue: await service.getByValue(myValue);
}
});
};
El mensaje de error es:
esperar es una palabra reservada
¿Por qué no puedo usarlo así?
algún día solitario
No puedes hacer esto como imaginas, porque no puedes usar await
si no está directamente dentro de un async
función.
Lo más sensato sería pasar la función a map
asincrónico. Esto significa que map
devolvería una serie de promesas. Entonces podemos usar Promise.all
para obtener el resultado cuando todas las promesas regresen. Como Promise.all
devuelve una promesa, la función externa no necesita ser async
.
const someFunction = (myArray) => {
const promises = myArray.map(async (myValue) => {
return {
id: "my_id",
myValue: await service.getByValue(myValue)
}
});
return Promise.all(promises);
}
-
en este caso, la matriz de promesas no es más lenta que la clásica para let in array?
– stackdave
3 de marzo de 2018 a las 6:38
-
@stackdave Probablemente, pero la diferencia será intrascendente al lado de
service.getByValue
que bien puede implicar una llamada de red…– algún día solitario
3 de marzo de 2018 a las 15:23
-
gracias, comencé a usarlo, de todos modos, la legibilidad es mejor que la velocidad, porque la mayoría de las técnicas asincrónicas de ES6 siempre serán más lentas, pero a quién le importa
– stackdave
3 de marzo de 2018 a las 15:37
-
@lonesomeday ¿Puede esto manejar errores o limitaciones/retrasos entre llamadas?
–Kyle Pennell
25 de noviembre de 2019 a las 20:05
-
@KylePennell Sí. Necesitaría manejar los errores con un
try..catch
en la función asíncrona o con uncatch
controlador antes de regresar de la función externa. Se podría introducir un acelerador antes de quereturn
en la función asíncrona.– algún día solitario
30 de noviembre de 2019 a las 14:41
Si desea ejecutar map con una función de mapeo asíncrono, puede usar el siguiente código:
const resultArray = await Promise.all(inputArray.map(async (i) => someAsyncFunction(i)));
Cómo funciona:
inputArray.map(async ...)
devuelve una matriz de promesas, una para cada valor eninputArray
.- Poniendo
Promise.all()
alrededor de la matriz de promesas lo convierte en una sola promesa. - La única promesa de
Promise.all()
devuelve una matriz de valores: el individuo promete que cada uno se resuelve en un valor. - Nosotros ponemos
await
en frente dePromise.all()
para que esperemos a que la promesa combinada se resuelva y almacene la matriz de subpromesas resueltas en la variableresultArray
.
Al final obtenemos un valor de salida en resultArray
para cada artículo en inputArray
mapeada a través de la función someAsyncFunction
. Tenemos que esperar a que se resuelvan todas las funciones asíncronas antes de que el resultado esté disponible.
infierno
Eso es porque la función en map
no es asíncronoasí que no puedes tener esperar en su declaración de devolución. Se compila con esta modificación:
const someFunction = async (myArray) => {
return myArray.map(async (myValue) => { // <-- note the `async` on this line
return {
id: "my_id",
myValue: await service.getByValue(myValue)
}
});
};
Entonces… no es posible dar una recomendación sin ver el resto de su aplicación, pero dependiendo de lo que esté tratando de hacer, haga la interno funcione de forma asíncrona o intente idear una arquitectura diferente para este bloque.
Actualización: es posible que obtengamos una espera de nivel superior algún día: https://github.com/MylesBorins/proposal-top-level-await
-
gracias, votado a favor, pero su código devuelve una matriz con objetos vacíos (es decir,
[{}, {}]
). Creo que necesito incluir en alguna parteawait
pero no podía darme cuenta de dónde– Bienvenido a
27 de febrero de 2017 a las 16:13
-
Lo que hace el
service.getByValue
función parece?– ayuda
27 de febrero de 2017 a las 16:19
-
simplemente devuelve ES6 Promise
– Bienvenido a
27 de febrero de 2017 a las 18:03
-
Me parece que el OP espera una serie de objetos identificados como resultado final, así que de acuerdo con eso, creo que probablemente quieras
return await Promise.all(myArray.map
… por equivalencia.– foque
27 de febrero de 2017 a las 21:33
serán 2 instrucciones, pero solo cambie “esperar” con la instrucción adicional
let results = array.map((e) => fetch('....'))
results = await Promise.all(results)
Intenté todas estas respuestas pero ninguna funciona para mi caso porque todas las respuestas devuelven un promise
objeto no el result of the promise
como esto:
{
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Array(3)
0: ...an object data here...
1: ...an object data here...
2: ...an object data here...
length: 3
[[Prototype]]: Array(0)
}
Luego encontré esta respuesta https://stackoverflow.com/a/64978715/8339172 que establece si map
la función no es asíncrona ni tiene en cuenta las promesas. Así que en lugar de usar await
en el interior map
función, yo uso for
bucle y await
el elemento individual porque dijo que for
el bucle es async
consciente y pausará el ciclo.
Cuando desee que se resuelva cada valor reasignado antes de pasar al siguiente, puede procesar la matriz como un iterable asíncrono.
A continuación, usamos la biblioteca iter-opspara reasignar cada valor en promesa, y luego producir un objeto con valor resuelto, porque map
en sí mismo no debería manejar ninguna promesa internamente.
import {pipe, map, wait, toAsync} from 'iter-ops';
const i = pipe(
toAsync(myArray), // make asynchronous
map(myValue => {
return service.getByValue(myValue).then(a => ({id: 'my_id', myValue: a}))
}),
wait() // wait for each promise
);
(async function() {
for await (const a of i) {
console.log(a); // print resulting objects
}
})
Después de cada valor, usamos Espere para resolver cada valor reasignado a medida que se genera, para mantener el requisito de resolución consistente con la pregunta original.
No creo que puedas tener funciones de flecha asíncronas.
– Puntiagudo
27 de febrero de 2017 a las 15:49
Importante github.com/tc39/ecmascript-asyncawait/issues/7
– Jared Smith
27 de febrero de 2017 a las 15:51
Para resumir de la discusión de github vinculada, no puede hacer eso porque la función anónima que está pasando como devolución de llamada no es
async
y el interiorawait
no puede afectar la función exterior.– Jared Smith
27 de febrero de 2017 a las 15:55
async/await
es parte de ES2017 (lanzamiento de este año), no de ES7 (lanzamiento del año pasado).– Félix Kling
1 de marzo de 2017 a las 14:34