Tengo esta matriz de objetos.
const items = [ { quantity: '2', name: 'john', type: 'https://api/event/1', }, { quantity: '3', name: 'jane', type: 'https://api/event/2', } ] para cada objeto en la matriz, necesito llamar a la API n veces según el valor de la quantity del objeto. Llamar a la API básicamente generará un enlace único. Sé que esto no es lo mejor para el rendimiento, pero esta es una aplicación pequeña y estaríamos haciendo entre 3 y 5 llamadas API en el peor de los casos, generalmente 1 tbh. En este caso, tengo 2 objetos en la matriz, el primero tiene 2 llamadas a la API y el segundo tiene 3 llamadas a la API. Cada vez que llamo a la API, quiero guardar el resultado (enlace único) en una matriz para poder enviarlos por correo electrónico al cliente que los compró.
Esto es lo que he intentado hasta ahora pero no ha funcionado:
const promises = [] const getLinks = async (arr) => { for (var i = 0; i < arr.length; i++) { for (var j = 0; j < arr[i].quantity; j++) { const getLink = (owner) => { axios.request({ method: 'POST', url: 'https://api.call' }) .then(function (response) { const promise = response.data.url promises.push(promise) }) .catch(error => console.log(error)) } } } const links = await Promise.all(promises) console.log('links:', links) // === [] this is always empty === } getLinks(items)Una cosa que aprendí es que await no puede ser y ralentizará el código drásticamente dentro de los bucles.
Parece que no puedo hacer que funcione
getLink nunca se llama en su código.Promise.all(promises) , la matriz de promises aún está vacía porque then completa en la devolución de llamada que se ejecuta más tarde.url de la respuesta a la matriz en lugar de empujar las promesas reales devueltas por axios const promises = [] for (const o of items) { for (let i = 0; i < o.quantity; i++) { const promise = axios.request({ method: post, url: o.type }) promises.push(promise) } } const responses = await Promise.all(promises) const urls = responses.map(r => r.data.url) O bien, puede usar flatMap obtener una matriz de todas las promesas devueltas por axios y usar Promise.all en la matriz resultante.
const promises = items.flatMap(o => Array.from({ length: o.quantity }, _ => axios.request({ method: post, url: o.type }) ) const responses = await Promise.all(promises)Estás un poco confundido acerca de cómo funcionan las Promesas.
/* THIS THING IS A PROMISE -> */ axios.request({ method: 'POST', url: 'https://api.call' }) .then(function (response) { const promise = response.data.url // <-THIS THING IS NOT A PROMISE }) La Promise es el valor de axios.request() . Por lo tanto, si quieres la promesa, debes hacer esto:
const promise = axios.request(); ¡El valor dentro de .then() NO es una Promise ! Es el valor devuelto por la promesa:
const promoise = axios.request({ method: 'POST', url: 'https://api.call' }) .then(function (response) { const result = response.data.url; return result; }) ¡Por lo tanto, ha estado presionando algo completamente incorrecto en su conjunto de promises ! Ha estado presionando la cadena de URL devuelta por su llamada api en lugar de las promesas.
Para que su código funcione correctamente es extremadamente simple:
const getLinks = async (arr) => { let promises = [] for (var i = 0; i < arr.length; i++) { for (var j = 0; j < arr[i].quantity; j++) { const getLink = (owner) => { const promise = axios.request({ method: 'POST', url: 'https://api.call' }) .then(function (response) { return response.data.url }) .catch(error => console.log(error)) promises.push(promise) } } } const links = await Promise.all(promises) console.log('links:', links) }//Map methods return an array const apiResponse = items.map(async(apiCall) => { // call an api here and store its result in a veriable let returnedResult await axios.get(apiCall.type) .then(response => { //refactor the reponse to how you want to store it in the array returnedResult = response }) return returnedResult }) Promise.all(apiResponse) .then(response => { console.log(response) // sent an email here based on the response you get })