Pensé que los bucles for estaban bloqueando en Javascript, pero esta función devuelve una matriz vacía antes de que finalice el bucle for. ¿La respuesta a esto es configurar una nueva función con solo el bucle for como promesa? Si es así, ¿cómo se ve eso? La sintaxis de una promesa es realmente confusa para mí.
async function retrieve_s3_file(to_do_list, guid){ var data_list = []; for (let i = 0; i < to_do_list.length; i++) { element = to_do_list[i]; console.log("\n\nOutgoing request /jobs/list?guid=" + guid + "&file=" + element); axios.get(job_queue_url + "?guid=" + guid + "&file=" + element) .then(function (res){ data_list.push(res.data); console.log("Inside Loop: " + JSON.stringify(data_list)); }) .catch(function (error){ console.log(error); }); } console.log("Data List: " + JSON.stringify(data_list)); return JSON.stringify(data_list); }Javascript tiene un solo subproceso y, por lo tanto, los bucles generalmente se bloquean, pero en este caso sus promesas pondrán sus nuevas tareas al final de la pila. Si usa await, no se debe crear ninguna tarea nueva y se debe comportar como usted desea. Pero lo estás haciendo sincronizado, por lo que será un poco más lento que antes.
async function retrieve_s3_file(to_do_list, guid){ var data_list = []; for (let i = 0; i < to_do_list.length; i++) { element = to_do_list[i]; console.log("\n\nOutgoing request /jobs/list?guid=" + guid + "&file=" + element); await axios.get(job_queue_url + "?guid=" + guid + "&file=" + element) .then(function (res){ data_list.push(res.data); console.log("Inside Loop: " + JSON.stringify(data_list)); }) .catch(function (error){ console.log(error); }); } console.log("Data List: " + JSON.stringify(data_list)); return JSON.stringify(data_list); }axios.get es una promesa. En javascript, una promesa no bloquea, lo que significa que la devolución de llamada proporcionada en la función then se ejecutará una vez que se resuelva la promesa. Pero la promesa no bloqueará el hilo.
El siguiente ejemplo refleja el problema de la pregunta. La consola imprime start end y luego ok . Debido a que customPromise es una promesa y se llama sin await , la persona que llama no esperará a que finalice esa promesa, por lo que la persona que llama continuará con la ejecución e imprimirá end . Tenga en cuenta que esta promesa se resuelve de inmediato, pero la devolución de llamada res => console.log(res) se ejecutará al final porque es una devolución de llamada de promesa.
const customPromise = new Promise((resolve, reject)=>{resolve('ok')}) function nonBLockingExample (){ console.log('start'); customPromise.then(res => console.log(res)); console.log('end'); } nonBLockingExample(); A continuación se muestra un ejemplo de la salida deseada. La persona que llama espera a que customPromise se resuelva porque customPromise se llama con la palabra clave await .
const nonBlockingPromise = new Promise((resolve, reject)=>{resolve('ok')}) async function bLockingExample (){ console.log('start'); await nonBlockingPromise.then(res => console.log(res)); console.log('end'); } bLockingExample(); Entonces, para aplicar la solución a su código, solo espere axios.get . ( await axios.get(..... )
Si usa la operación asincrónica, no se bloqueará.
Puede usar la palabra clave await si desea que Axios espere antes de que finalice la solicitud; de lo contrario, use promesas. Recójalos y usando Promise.all puede obtener todas las respuestas como una matriz cuando se resuelvan todas las solicitudes.
async function retrieve_s3_file(to_do_list, guid) { const requests = []; for (const file of to_do_list) { const params = new URLSearchParams({ guid, file }); const request = axios.get(`${job_queue_url}?${params.toString()}`); requests.push(request.then((response) => response.data)); } return Promise.all(requests).then(JSON.stringify); }