He estado luchando por entender qué es lo que está mal con esto por un tiempo, pero todavía no puedo darme cuenta de lo que estoy haciendo mal. Estoy tratando de agregar a la base de datos cada artículo de la cesta del usuario como un artículo de pedido, con esta función .map () (un artículo de pedido en la base de datos corresponde a un producto, que no es realmente relevante para la pregunta pero ayuda si usted es luchando por entender la operación):
const orderItems= orderData.map(async product=>{ const productId=product.id.slice(0,product.id.length-5) const targetProduct=await dataSources.ProductAPI.product(productId) const name=targetProduct.name const quantity=218327 await dataSources.OrderItemAPI.createOrderItem(orderId,productId,name,quantity,{ttlInSeconds:60*20}) })
Luego, estoy tratando de asignar cada artículo de pedido de la matriz de artículos de orderItems
anterior a un producto real en la base de datos, como este:
//encontramos el producto correspondiente a cada artículo de pedido
const productsCorrespondingToOrderItems= orderItems.map(async orderItem=>{ const trial=await orderItem console.log(trial) <--- returns undefined // OR just logging orderItem returns a promise await dataSources.TransactionAPI.findProductFromOrderItem(orderItem.productId).then(x=>console.log(x)) })
He comprobado cada artículo de los artículos del pedido y se ve bien. El problema es que cada orderItem
en productsCorrespondingToOrderItems
devuelve una promesa, cuando simplemente lo estoy registrando, o indefinido si lo espero. Realmente no entiendo, ¿qué estoy haciendo mal? Muchas gracias !
Las funciones async
siempre devuelven una promesa. No está devolviendo nada de las devoluciones de llamada de su map
, por lo que dado que las devoluciones de llamada son funciones async
, devuelven promesas que se cumplen con undefined
.
Si desea esperar a que se cumplan todas las promesas de las operaciones de su map
, use Promise.all
en el resultado. Promise.all
devuelve una promesa que se cumplirá con una matriz de los valores de cumplimiento de las promesas que le das (si se cumplen todas) o se rechazará la primera vez que alguna de ellas rechace. Espera esa promesa con await
(en una función async
) o llamando a .then
/ .catch
.
Aquí hay un ejemplo que asume que el código donde está haciendo ese map
no está en una función async
:
// If not in an `async` function Promise.all(orderData.map(async product => { const productId = product.id.slice(0, product.id.length - 5); const targetProduct = await dataSources.ProductAPI.product(productId); const name = targetProduct.name; const quantity = 218327; const orderItem await dataSources.OrderItemAPI.createOrderItem( orderId, productId, name, quantity, { ttlInSeconds: 60 * 20 } ); return await dataSources.TransactionAPI.findProductFromOrderItem(orderItem.productId); })) .then(productsCorrespondingToOrderItems => { // ...use `productsCorrespondingToOrderItems` here... }) .catch(error => { // ...handle/report error... });
Tenga en cuenta que eso hace el trabajo en paralelo . Si desea hacerlo en serie, use una función async
y un bucle for-of
.
No devolvió nada de su mapa y el mapa no funciona para async/await. Haga esto en su lugar para llamar a la API una vez a la vez (en serie). Si desea esperar varias llamadas api al mismo tiempo (en paralelo), use la respuesta de TJ Crowder.
const orderItems= []; for (const product of orderData) { const productId=product.id.slice(0,product.id.length-5) const targetProduct=await dataSources.ProductAPI.product(productId) const name=targetProduct.name const quantity=218327 await dataSources.OrderItemAPI.createOrderItem(orderId,productId,name,quantity,{ttlInSeconds:60*20}) }) // push something to the orderItems array here! }