En este momento tengo una página web en la que se están realizando una larga lista de llamadas Axios POST. Ahora, las solicitudes parecen enviarse en paralelo (JavaScript continúa enviando la siguiente solicitud antes de recibir el resultado).
Sin embargo, los resultados parecen devolverse uno por uno, no simultáneamente. Digamos que una llamada POST al script PHP toma 4 segundos y necesito hacer 10 llamadas. Actualmente tardaría 4 segundos por llamada, que serían 40 segundos en total. Espero encontrar una solución para ambos y recibir todos los resultados aproximadamente al mismo tiempo (~4 segundos) en lugar de ~40 segundos.
Ahora he leído sobre subprocesos, subprocesos múltiples en NodeJS usando Workers. He leído que JavaScript en sí solo tiene un solo subproceso, por lo que es posible que no lo permita por sí mismo.
Pero no estoy seguro de adónde ir desde aquí. Todo lo que tengo son algunas ideas. No estoy seguro de si me estoy dirigiendo o no en la dirección correcta y, si lo estoy, no estoy seguro de cómo usar Workers en NodeJS y aplicarlo en mi código. ¿Qué camino debo tomar? ¡Cualquier orientación sería muy apreciada!
Aquí hay una pequeña pieza de código de ejemplo:
for( var i = 0; i < 10; i++ ) { window.axios.post(`/my-url`, { myVar: 'myValue' }) .then((response) => { // Takes 4 seconds, 4 more seconds, 4 more seconds, etc // Ideally: Takes 4 seconds, returns in the same ~4 seconds, returns in the same ~4 seconds, etc console.log( 'Succeeded!' ); }) .catch((error) => { console.log( 'Error' ); }); // Takes < 1 second, < 1 more second, < 1 more second, etc console.log( 'Request sent!' ); }Prueba de esta manera
window.axios.all([requestOne, requestTwo, requestThree]) .then(axios.spread((...responses) => { const responseOne = responses[0] const responseTwo = responses[1] const responesThree = responses[2] // use/access the results })).catch(errors => { // react on errors. })Si desea tenerlo dentro de un bucle, puede tener una versión ligeramente modificada de @deelink como se muestra a continuación
let promises = []; for (i = 0; i < 10; i++) { promises.push( window.axios.post(`/my-url`, { myVar: 'myValue'}) .then(response => { // do something with response }) ) } Promise.all(promises).then(() => console.log('all done'));Pruebe esto con Axios.all y
Usar el método Promise.all() devuelve una Promesa única que se cumple cuando se han cumplido todas las promesas pasadas como un iterable Promise MDN ref Link
import axios from 'axios'; let one = "https://api1" let two = "https://api2" let three = "https://api3" const requestOne = axios.get(one); const requestTwo = axios.get(two); const requestThree = axios.get(three); axios.all([requestOne, requestTwo, requestThree]).then(axios.spread((...responses) => { const responseOne = responses[0] const responseTwo = responses[1] const responesThree = responses[2] // use/access the results console.log("responseOne",responseOne); console.log("responseTwo",responseTwo); console.log("responesThree",responesThree); })).catch(errors => { console.log(errors); })Enlace de referencia
Para solicitudes simultáneas con Axios, puede usar Axios.all().
axios.all([ axios.get('https://api.github.com/users/MaksymRudnyi'), axios.get('https://api.github.com/users/taylorotwell') ]) .then(axios.spread((obj1, obj2) => { // Both requests are now complete console.log(obj1.data.login + ' has ' + obj1.data.public_repos + ' public repos on GitHub'); console.log(obj2.data.login + ' has ' + obj2.data.public_repos + ' public repos on GitHub'); }));Además, puede usar Promise.all(). Funciona de manera similar:
Promise.all([ fetch('https://api.github.com/users/MaksymRudnyi'), fetch('https://api.github.com/users/taylorotwell') ]) .then(async([res1, res2]) => { const a = await res1.json(); const b = await res2.json(); console.log(a.login + ' has ' + a.public_repos + ' public repos on GitHub'); console.log(b.login + ' has ' + b.public_repos + ' public repos on GitHub'); }) .catch(error => { console.log(error); });Pero, con Promise.all() hay un comportamiento específico. En caso de que se rechace al menos una solicitud, se rechazarán todas las solicitudes y el código irá a las secciones .catch(). Está bien en caso de que necesite asegurarse de que se resuelvan todas las solicitudes.
En caso de que esté bien que algunas de sus solicitudes sean rechazadas, considere usar Promise.allSettled(). El método Promise.allSettled() devuelve una promesa que se resuelve después de que todas las promesas proporcionadas se hayan resuelto o rechazado, con una matriz de objetos que describen el resultado de cada promesa.
Esto es raro y no debería pasar. Los motores de Javascript son de un solo subproceso, pero las API web (que se utilizan internamente al realizar solicitudes AJAX) no lo son. Por lo tanto, las solicitudes deben realizarse aproximadamente al mismo tiempo y los tiempos de respuesta deben depender de los tiempos de procesamiento del servidor y los retrasos de la red.
Los navegadores web tienen un límite en la cantidad de conexiones por servidor (6 en Chrome https://bugs.chromium.org/p/chromium/issues/detail?id=12066 ) lo que explicaría algunas serializaciones. Pero no esto.
Dado que las solicitudes tardan 4 segundos, lo cual es largo , supongo que el servidor es el problema. Es posible que solo pueda manejar 1 conexión a la vez. ¿Tienes control sobre eso?
Hay tres casos a través de los cuales puede lograr su objetivo.
Para solicitudes simultáneas con Axios, puede usar Axios.all()
axios.all([ axios.post(`/my-url`, { myVar: 'myValue' }), axios.post(`/my-url2`, { myVar: 'myValue' }) ]) .then(axios.spread((data1, data2) => { // output of req. console.log('data1', data1, 'data2', data2) })); puede usar Promise.allSettled() . El método Promise.allSettled() devuelve una promesa que se resuelve después de que todas las promesas proporcionadas se hayan resuelto o rechazado.
Puede intentar usar Promise.all() pero tiene el inconveniente de que si falla 1 req, fallará para todos y dará o/p como un error (o en el bloque de captura)
pero el mejor de los casos es el primero.
Puedes usar de esta manera
const token_config = { headers: { 'Authorization': `Bearer ${process.env.JWD_TOKEN}` } } const [ res1, res2 ] = await Axios.all([ Axios.get(`https://api-1`, token_config), Axios.get(`https://api-2`, token_config) ]); res.json({ info: { "res_1": res1, "res_2": res2 } });