Estoy tratando de hacer 10 llamadas API a la API de reddit para obtener los comentarios más recientes de los usuarios.
Básicamente, Reddit usa un parámetro 'después' en el URI para pasar a la página siguiente. Básicamente, si hay algunos datos de comentarios de ejemplo ficticios a continuación, necesito la ÚLTIMA ID.
Ejemplo.
Llamada API: https://www.reddit.com/user/USERNAME/comments.json?limit=3
devoluciones:
{ id: 'd4gf125', comment: 'blah blah blah' }, { id: 'dag42ra', comment: 'blah blah blah' }, { id: 'hq6ir3j', // I need this ID right here, the LAST in the list for the next API call comment: 'blah blah blah' },Luego, se debe realizar otra llamada a la API directamente DESPUÉS de la anterior, utilizando la ID como parámetro.
Llamada API:
`https://www.reddit.com/user/USERNAME/comments.json?limit=3&after=tl_hq6ir3j`Esto se ejecutará 10 veces, lo que generará 10 páginas, por lo que en total, 30 resultados.
He intentado usar este bucle for pero como los bucles for no son asíncronos, no puedo cambiar la variable 'lastID' a tiempo.
Primer intento:
const handleSubmit = async () => { setLoading(true); axios.get(`${apiUrl}user/${username}/about.json`).then((res) => { setUserData({ about: res.data.data, }); axios .get(`${apiUrl}user/${username}/comments.json?limit=100`) .then((res) => { let data = res.data.data.children; let lastItem = data[data.length - 1]; for (i = 0; i < 10; i++) { axios .get( `${apiUrl}comments/${lastItem.data.id}/comments.json?limit=100&after=tl_${lastItem}` ) .then((res) => { lastItem = res.data.data.children[res.data.data.children.length - 1]; }); } }); }); };Si necesita algún ejemplo de datos REALES, consulte el siguiente enlace:
https://www.reddit.com/user/bulkorcut99/comments.json?limit=1000&after=t1_hq6ir3jPara hacer cosas asíncronas en secuencia, encadene promesas junto con then() . La forma genérica se ve así...
let promise = /* starting promise */ for (/* loop stuff */) { promise = promise.then(/*another promise*/) }Refactorizando tu código para que esto quede más claro...
function getAbout(username) { return axios.get(`${apiUrl}user/${username}/about.json`).then(res => { return res.data.data }); } function getComment(username, afterId) { const url = `${apiUrl}comments/${lastItem.data.id}/comments.jsonlimit=100`; if (afterId) url += `&after=tl_${afterId}`; return axios.get(url).then(res => res.data.data); } // create a chain of promises to get comments, pushing results as we go function getComments(username, results) { let promise = getComment(username); for (let i=0; i<10; i++) { // not sure why 10 here... from the OP promise = promise.then(data => { results.push(data); const lastChild = data.children[data.children.length-1]; return getComment(username, lastChild.id); }); } return promise; } const handleSubmit = async () => { setLoading(true); return getAbout(username).then(data => { setUserData({ about: data }); }).then(() => { let comments = []; return getComments(username, comments).then(() => comments) }).then(comments => { // comments is the result from all of the get comments calls }) }La API real podría dejar de encontrar comentarios en menos de 10 llamadas. Si es así, en lugar de repetir hasta 10, repetirá hasta que los resultados estén vacíos o cualquier condición que indique que no hay más.
Simplemente puede esperar cada una de sus llamadas axios.get en su bucle for. Para hacerlo puedes hacer algo como esto:
const handleSubmit = async () => { setLoading(true); axios.get(`${apiUrl}user/${username}/about.json`).then((res) => { setUserData({ about: res.data.data, }); axios .get(`${apiUrl}user/${username}/comments.json?limit=100`) .then(async (res) => { let data = res.data.data.children; let lastItem = data[data.length - 1]; for (i = 0; i < 10; i++) { var {data} = await axios .get(`${apiUrl}comments/${lastItem.data.id}/comments.json?limit=100&after=tl_${lastItem}`) lastItem = data.data.children[data.data.children.length - 1]; } }); }); };