此刻,我有一个网页,其中正在制作一长串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!' );
}
答案 0 :(得分:19)
有三种情况可以帮助您实现目标。
对于与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)
}));
您可以使用Promise.allSettled()
。 Promise.allSettled()方法返回一个承诺,该承诺将在所有给定的承诺都已解决或被拒绝后解决,
您可以尝试使用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);
})
引用链接
答案 5 :(得分:0)
这很奇怪,不应该发生。 Javascript引擎是单线程的,但Web API(在发出AJAX请求时在内部使用)不是。因此,应该大致同时发出请求,并且响应时间应取决于服务器处理时间和网络延迟。
Web浏览器对每个服务器的连接数有限制(chrome https://bugs.chromium.org/p/chromium/issues/detail?id=12066中为6),这可以解释一些序列化。但是不是这个。
由于请求需要4秒钟的时间,即 长 ,因此我猜测服务器是问题所在。它一次只能处理1个连接。你有控制权吗?