如何同时发布多个Axios请求?

时间:2020-04-23 10:52:56

标签: javascript node.js multithreading axios

此刻,我有一个网页,其中正在制作一长串Axios POST调用。现在,请求似乎是并行发送的(JavaScript在收到结果之前会继续发送下一个请求)。

但是,结果似乎是一个接一个地返回,而不是同时返回。假设一次对PHP脚本的POST调用需要4秒钟,而我需要进行10次调用。目前,每次通话需要4秒钟,总计40秒钟。我希望找到一种解决方案,并在大约同一时间(〜4秒)而不是大约40秒接收所有结果。

现在,我已经了解了有关线程的信息,以及使用Workers在NodeJS中进行多线程处理的知识。我已经读过JavaScript本身只是单线程的,因此它本身可能不允许这样做。

但是我不确定从这里去哪里。我所拥有的只是一些想法。我不确定我是否朝着正确的方向前进,如果可以,我不确定如何在NodeJS中使用Workers并将其应用到我的代码中。我应该走哪条路?任何指导将不胜感激!

这是一小段示例代码:

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!' );
}

6 个答案:

答案 0 :(得分:19)

有三种情况可以帮助您实现目标。

  1. 对于与Axios的同时请求,可以使用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)
     }));
    
  2. 您可以使用Promise.allSettled()。 Promise.allSettled()方法返回一个承诺,该承诺将在所有给定的承诺都已解决或被拒绝后解决,

  3. 您可以尝试使用Promise.all(),但是它的缺点是,如果任何 1 请求失败,则所有请求都会失败,并给出o / p作为错误(或在捕获块中

但最好的情况是第一个。

答案 1 :(得分:4)

对于同时请求Axios的请求,可以使用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');
}));

此外,您可以使用Promise.all()。相似的作品:

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);
});

但是,使用Promise.all()可以实现特定的行为。如果至少一个请求将被拒绝-所有请求将被拒绝,并且代码将转到.catch()部分。如果您需要确保所有请求都得到解决,就可以了。

在某些请求被拒绝的情况下,如果可以,请考虑使用Promise.allSettled()。 Promise.allSettled()方法返回一个承诺,该承诺在所有给定的承诺均已解决或被拒绝后将解决,并带有一系列对象,每个对象描述每个承诺的结果。

答案 2 :(得分:2)

以这种方式尝试

describe('Overview Test', () => {

  // Mock the module and its functions
  jest.mock('./someFile', () => ({
    __esModule: true,
    someFunction: jest.fn(() => 'Mocked someFunction!')
  }));

  // Import the function from the mocked module
  const { someFunction } = require('./someFile');

  test('snapshot', () => {
    // Execute the mocked function
    const someResult = someFunction();

    // Expect to return the mocked value
    expect(someResult).toBe('Mocked someFunction!');
  });

});

答案 3 :(得分:1)

如果您希望将其放入循环中,可以对@deelink进行如下修改,

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'));

答案 4 :(得分:1)

尝试使用Axios.all和

  • 使用Promise.all()方法将返回一个Promise,该条件将在满足作为迭代器传递的所有诺言时得到满足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);
    })
    

引用链接

Find full example here for axios

答案 5 :(得分:0)

这很奇怪,不应该发生。 Javascript引擎是单线程的,但Web API(在发出AJAX请求时在内部使用)不是。因此,应该大致同时发出请求,并且响应时间应取决于服务器处理时间和网络延迟。

Web浏览器对每个服务器的连接数有限制(chrome https://bugs.chromium.org/p/chromium/issues/detail?id=12066中为6),这可以解释一些序列化。但是不是这个。

由于请求需要4秒钟的时间,即 ,因此我猜测服务器是问题所在。它一次只能处理1个连接。你有控制权吗?