Básicamente, estoy tratando de escribir una función que devolverá una lista de puntajes de equipos con los nombres de los equipos junto a su puntaje. Sin embargo, debido a que la función que recupera el nombre del equipo devuelve una promesa pendiente, nunca puedo ver los nombres en la consola.
¿Cómo resuelvo estas promesas para que en el siguiente bloque .then de la cadena de promesas pueda ver los nombres de los equipos a ambos lados de las puntuaciones en lugar de [object Promise] .
[En esta imagen se puede ver la función completa con las dos funciones fetchTeamNames almacenadas en las variables][1]
La función fetchFullTimeHeadToHeadScore es la función principal:
function fetchFullTimeHeadToHeadScore(homeTeamId, awayTeamId) { return axios .get( `https://soccer.sportmonks.com/api/v2.0/head2head/${homeTeamId}/${awayTeamId}?api_token=${apiKey}` ) .then((res) => { const homeSide = fetchTeamName(homeTeamId).then((res) => { return res; }); const awaySide = fetchTeamName(awayTeamId).then((res) => { return res; }); return [homeSide, res.data.data, awaySide]; }) .then((data) => { return data[1].map((obj) => { return data[0] + " " + obj.scores.ft_score + " " + data[2]; }); }) .then((scores) => { scores.length = 10; return scores; }) .catch((err) => { console.log(err); }); } ... que llama a la función fetchTeamName :
function fetchTeamName(teamId) { return axios .get( `https://soccer.sportmonks.com/api/v2.0/teams/${teamId}?api_token=${apiKey}` ) .then((res) => { return res.data.data.name; }); } ... que en la consola esperaría que me permitiera ver los nombres de los equipos, pero actualmente solo genera [object Promise] :
- Expected - 10 + Received + 10 Array [ - "1-2", - "3-0", - "1-0", - "4-1", - "1-1", - "1-0", - "0-2", - "1-2", - "0-2", - "2-0", + "[object Promise] 1-2 [object Promise]", + "[object Promise] 3-0 [object Promise]", + "[object Promise] 1-0 [object Promise]", + "[object Promise] 4-1 [object Promise]", + "[object Promise] 1-1 [object Promise]", + "[object Promise] 1-0 [object Promise]", + "[object Promise] 0-2 [object Promise]", + "[object Promise] 1-2 [object Promise]", + "[object Promise] 0-2 [object Promise]", + "[object Promise] 2-0 [object Promise]", ]Parece que estás recibiendo promesas no gestionadas.
Creo que podría usar Async y esperar: lo que esto hará es evitar que su código se compile cuando envíe su solicitud de get . Hacer que el código espere hasta que se cumpla la solicitud, hasta que continúe compilando.
Este es un enlace a un artículo que podría ayudarlo a comenzar :)
https://dev.to/tutrinh/basic-using-async-and-await-with-axios-ad5
[editar]
Esta es una idea aproximada de cómo podría verse; espero que esto ayude un poco.
const fetchTeamName = async(teamId) => { try{ const response = await axios.get(`https://soccer.sportmonks.com/api/v2.0/teams/${teamId}?api_token=${apiKey}`) return response.data.data.name } }Si usa await para esperar promesas en lugar de usar then , podría ser más fácil de leer (y escribir).
const res = await axios.get(`xxxx`) const scores = res.data.data; Una palabra de advertencia: no explicó dónde pretende ejecutar este código y cuál es su proceso de compilación (si corresponde). await no siempre está disponible sin usar una herramienta como Babel o esbuild para convertir JavaScript moderno a JavaScript que sea compatible con una amplia gama de navegadores.
Sin embargo, suponiendo que está ejecutando su código en un entorno compatible con async / await , también puede utilizar la función Promise.all para esperar a que se completen las 3 promesas.
async function fetchFullTimeHeadToHeadScore(homeTeamId, awayTeamId) { const homeTeamNamePromise = fetchTeamName(homeTeamId); const awayTeamNamePromise = fetchTeamName(awayTeamId); const scorePromise = fetchScore(homeTeamId, awayTeamId); // axios.fetch const results = await Promise.all([ homeTeamNamePromise, awayTeamNamePromise, scorePromise ]); const homeTeamName = results[0]; const awayTeamName = results[1]; const matches = results[2]; return matches.map(match => `${homeTeamName} ${match.scores.ft_score} ${awayTeamName}`); }Si realmente necesita que esto funcione con promesas, este artículo lo explica: https://javascript.info/promise-chaining
Aquí está el código relevante:
// Make a request for user.json fetch('/article/promise-chaining/user.json') // Load it as json .then(response => response.json()) // Make a request to GitHub .then(user => fetch(`https://api.github.com/users/${user.name}`)) // Load the response as json .then(response => response.json()) // Show the avatar image (githubUser.avatar_url) for 3 seconds (maybe animate it) .then(githubUser => { let img = document.createElement('img'); img.src = githubUser.avatar_url; img.className = "promise-avatar-example"; document.body.append(img); setTimeout(() => img.remove(), 3000); // (*) }); En su caso, parece que puede colocar un Promise.all([ homeSide, res.data.data, awaySide ]); en su código para devolver las promesas resueltas para homeSide y awaySide , y el valor real de res.data.data (aunque no sea una promesa).
function fetchFullTimeHeadToHeadScore(homeTeamId, awayTeamId) { return axios .get( `https://soccer.sportmonks.com/api/v2.0/head2head/${homeTeamId}/${awayTeamId}?api_token=${apiKey}` ) .then((res) => { const homeSide = fetchTeamName(homeTeamId) const awaySide = fetchTeamName(awayTeamId) return Promise.all([ homeSide, res.data.data, awaySide ]); }) .then((data) => { return data[1].map((obj) => { return data[0] + " " + obj.scores.ft_score + " " + data[2]; }); }) .then((scores) => { scores.length = 10; return scores; }) .catch((err) => { console.log(err); }); }fetchTeamName devuelve una Promise no resuelta, cuyo valor de retorno solo es accesible dentro de la función de éxito ( .then(onFulfillment, onRejection) ). Creo que has reconocido esto, por lo que has hecho fetchTeamName(foo).then((res) => res) , pero la idea errónea es que no te has dado cuenta de que esto también devuelve una Promise .
No hay forma de acceder al resultado de una Promise fuera del alcance de sus métodos de instancia ( .then() , .catch() , etc.).
Probablemente podrías hacer algo como
fetchTeamName(homeTeamId).then((homeSide) => { fetchTeamName(awayTeamId) .then((awaySide) => { return res.data.data.map((obj) => { return `${homeSide} ${obj.scores.ft_score} ${awaySide}`; }); }) .then((scores) => { scores.length = 10; return scores; }); }); pero probablemente esté pensando "espere, el valor de awaySide no depende del valor de homeSide , entonces, ¿por qué estoy esperando que se complete esa llamada API antes de comenzar la llamada para obtener el valor de awaySide "?
¡Tendrías razón al pensar esto! Una mejor solución utiliza Promise.all :
const homeSidePromise = fetchTeamName(homeTeamId); const awaySidePromise = fetchTeamName(awayTeamId); Promise.all([homeSidePromise, awaySidePromise]) .then(([homeSide, awaySide]) => { return res.data.data.map((obj) => { return `${homeSide} ${obj.scores.ft_score} ${awaySide}`; }); }) .then((scores) => { scores.length = 10; return scores; }); Esto es mejor, pero aún es difícil de leer y no mucho mejor que el infierno de devolución de llamada que solía tener antes de que Promise s fuera una función de lenguaje ampliamente compatible.
Un patrón más moderno implica el uso de async / await . Esta sintaxis todavía usa Promise s "debajo del capó", pero lo ayuda a escribir código que es mucho más legible. Dejaré la reescritura de su ejemplo de código con async / await como ejercicio para el lector.