Antes de comenzar, permítanme decir que soy nuevo en Javascript y muy nuevo en las llamadas a la API de axios, por lo que probablemente esté cometiendo un error de novato...
Tengo esta función getObjects() que está destinada a mapear una matriz y devolver los datos de una llamada a la API de Axios. La función de asignación y llamada de la API funcionan, pero obtengo un objeto Promesa en lugar de los datos que intento obtener.
Me imagino que esto se debe a que los datos se devuelven antes de que haya tiempo suficiente para obtenerlos, pero ¿no está seguro de cómo solucionarlo? Probé un .setTimeout() , pero eso no pareció funcionar.
getObjects() { let newsItems = this.state.arrayofids.map((index) => { let resultOfIndex = axios.get(`https:\/\/hacker-news.firebaseio.com/v0/item/${index}.json`).then((res) => { let data = res.data; //console.log(data.by); // this prints the correct byline, but // all the bylines are printed after // the console.log below... if (!data.hasOwnProperty('text')) return data; }); /// end of axios request return resultOfIndex; }); /// end of map /// ideally this would end in an array of response objects but instead i'm getting an array of promises... console.log(newsItems); }(Los caracteres de escape adicionales son para el beneficio de mi editor de texto).
Aquí hay un enlace a un codepen con el problema : abra la consola para ver el problema. Es un proyecto de React, pero no creo que ninguna de las cosas de React sea el problema. EDITAR: Codepen es un enlace a la solución de trabajo usando axios.all como se sugiere a continuación
¡Gracias!
EDITAR: Aquí está mi solución de trabajo.
getObjects() { let axiosArr = []; axios.all(this.state.arrayofids.map((id) => { return axios.get(`https:\/\/hacker-news.firebaseio.com/v0/item/${id}.json`) })).then((res) => { for (let i = 0; i < this.state.arrayofids.length; i++) { axiosArr.push(<li key={i} data-url={res[i].data.url} onClick={(e) => this.displayTheNews(e)}>{res[i].data.title}</li>); } if (axiosArr.length == this.state.arrayofids.length) { this.setState({arrayofdata: axiosArr}); console.log('state is set!'); } }) }La función axios.all debería ser más apropiada para su escenario actual.
Su console.log se ejecuta inmediatamente, en lugar de esperar a que finalicen las solicitudes, porque no son síncronas. Tienes que esperar todas las respuestas antes de console.log .
OPCIÓN 1 (de la manera difícil): reemplace su console.log con
newsItems.forEach((promise, index) => { promise.then((object)=>{ newsItems[index] = object if (index+1 == newsItems.length) { console.log(newsItems) } }) }) OPCIÓN 2 (la mejor manera): usando axios.all
getObjects() { axios.all(this.state.arrayofids.map((id) => { return axios.get(`https:\/\/hacker-news.firebaseio.com/v0/item/${id}.json`) })).then((res) => { console.log(res) }) }por cierto, definitivamente recomendaría cambiar
this.state.arrayofids.map((index) => { let resultOfIndex = axios.get(`https:\/\/hacker-news.firebaseio.com/v0/item/${index}.json`)... para ser llamado id en lugar de index