Javascript 如何使用Promise.all处理数千个请求
在我的React应用程序中,我有一个组件可以向一个在线服务发送请求,该服务最多可以处理50个请求。我现在收到了一个新的请求,可以执行7000个MACJavascript 如何使用Promise.all处理数千个请求,javascript,reactjs,promise,axios,Javascript,Reactjs,Promise,Axios,在我的React应用程序中,我有一个组件可以向一个在线服务发送请求,该服务最多可以处理50个请求。我现在收到了一个新的请求,可以执行7000个MAC function App() { const [data, setData] = useState([]); useEffect(() => { const fetchData = async () => { await axios.all([ axios.get("/ip
function App() {
const [data, setData] = useState([]);
useEffect(() => {
const fetchData = async () => {
await axios.all([
axios.get("/ipdn/<MAC ADDRESS>", { timeout: 10000 }),
axios.get("/ipdn/<MAC ADDRESS>", { timeout: 10000 })
// Adding all the mac address .......
]).then((responseArr) => {
setData(responseArr)
});
};
fetchData();
}, []);
函数应用程序(){
const[data,setData]=useState([]);
useffect(()=>{
const fetchData=async()=>{
等待axios([
get(“/ipdn/”,{timeout:10000}),
get(“/ipdn/”,{timeout:10000})
//正在添加所有mac地址。。。。。。。
]).然后((响应)=>{
设置数据(应答器)
});
};
fetchData();
}, []);
我想扩展fetchData函数,这样它基本上只发送50个IP,并等待迭代完成
迭代完成后,将执行下一个50
谢谢如果您在使用外部库时没有任何问题,您可以使用来管理并发请求,如下所示
import PromisePool from 'es6-promise-pool';
// macs - Array of mac addresses
useEffect(() => {
const fetchData = () => {
const results = [];
const generatePromises = function*() {
for (let count = 0; count < macs.length; count++) {
yield axios.get(`/ipdn/${macs[count]}`, ...);
}
}
const promiseIterator = generatePromises();
// Create a pool with 10 concurrent requests max
const pool = new PromisePool(
promiseIterator,
10 // Configurable
);
// To listen to result
pool.addEventListener('fulfilled', function (event) {
console.log('Fulfilled: ' + event.data.result);
results.push(event.data.result);
});
// Start the pool
pool.start().then(function () {
setData(results);
console.log('Complete');
});
};
fetchData();
}, []);
从“es6承诺池”导入承诺池;
//mac-mac地址数组
useffect(()=>{
常量fetchData=()=>{
常量结果=[];
const generatePromises=函数*(){
对于(让count=0;count,以下是在没有任何外部库的情况下如何执行此操作:
const ips = [
/* List of mac address. */
];
useEffect(() => {
const fetchData = async () => {
const loadedData = [];
// Iterate over the slices of array until all the ips have been processed.
for (const sliceIps of sliceGenerator(ips)) {
const gettingData = sliceIps.map(getDataFromIp);
const sliceLoadedData = await axios.all(gettingData);
loadedData = loadedData.concat(sliceLoadedData);
}
setData(loadedData);
};
fetchData();
}, []);
const getDataFromIp = (ip) =>
axios.get("/ipdn/<MAC ADDRESS>", { timeout: 10000 });
// Generates a slice of an array, here the slice has a size of 50 max.
function* sliceGenerator(arr) {
const sliceSize = 50;
let i = 0;
while (i < arr.length) {
yield arr.splice(i, i + sliceSize);
i += sliceSize;
}
}
const-ips=[
/*mac地址列表*/
];
useffect(()=>{
const fetchData=async()=>{
常量loadedData=[];
//迭代数组的切片,直到处理完所有IP。
用于(切片生成器(ips)的常量切片ips){
const gettingData=sliceIps.map(getDataFromIp);
const sliceLoadedData=等待axios.all(获取数据);
loadedData=loadedData.concat(sliceLoadedData);
}
设置数据(加载数据);
};
fetchData();
}, []);
const getDataFromIp=(ip)=>
get(“/ipdn/”,{timeout:10000});
//生成数组的一个切片,此处切片的最大大小为50。
函数*切片生成器(arr){
常数切片大小=50;
设i=0;
而(i
我在这里使用生成器函数*sliceGenerator
来生成ips阵列的切片。这样你就可以对它们进行50×50的批处理
我还为(…of…)
循环使用了。这非常方便,因为您可以在内部使用wait
关键字。没有库,您可以使用此函数:
function poolPromises(iterPromises, poolSize) {
return new Promise((resolve, reject) => {
let promises = [];
function nextPromise() {
let { value, done } = iterPromises.next();
if (done) {
resolve(Promise.all(promises));
} else {
promises.push(value); // value is a promise
value.then(nextPromise, reject);
}
return !done;
}
while (promises.length < poolSize && nextPromise()) { }
});
}
注意:fetchData
不必声明为async
,因为那里没有等待
。我不熟悉axios.all
,然后我提供了一种方法,只需使用Promise.all
。我的想法是将输入数组拆分为每个块50个地址,然后逐个求解
函数应用程序(){
const[data,setData]=useState([]);
useffect(()=>{
//辅助函数,将数组拆分为分块数组
const splitToChunks=(项目,chunkSize=50)=>{
常量结果=[];
for(设i=0;i{
常量结果=[];//初始值
const macaddress=[];//mac地址数组-您的mac地址
const chunkedArray=splitToChunks(macaddress);//返回数组的数组[[…50 mac adds],[],[]
对于(chunkedArray的常量mac){//现在macs是[…50 mac添加]
const promises=macs.map((mac)=>{
返回axios.get(`/ipdn/${mac}`,{timeout:10000});
});
//现在承诺是数组包含50个承诺
const response=wait Promise.all(promises);//等待完成50个请求
result.push(…response);//将响应复制到result,并继续下一个块
}
设置数据(结果);
};
fetchData();
}, []);
}
利用。它可以帮助您管理并行请求的并发性。您是否可以完成您的代码,以便清楚mac地址存储在哪里,以及如何将它们传递到请求?呃,只是不要编写客户端组件来执行7000个HTTP请求。谢谢Prathap。您可以添加一些代码,看看如何合并这些请求使用useffect。在useffect
中移动逻辑并捕获结果。在池执行完成后,您可以将其移动到数组中并使用setData
对其进行设置。(未添加错误处理)感谢大家提供了出色的解决方案。Prathap我将投票支持您的答案,因为我正在使用此答案。请考虑@Bergi注释(来自客户的7000个请求)以及考虑,以防有任何方法说服你的老板。(考虑缓慢/不可靠的互联网连接、移动网络等).Happy coding为什么使用async if await没有使用?这是因为我等待axios。所有的都在循环中。你的意思是使用while循环而不是if
语句吗?@PrathapReddy这就是我想说的,他的函数只有一个产量,所以它只会给出第一个拼接。他应该在生成器函数中使用一个循环。嗨s函数将给出一个长度为50的嵌套数组。@ramesheldy,我的错。没有观察到。他应该使用循环而不是if
。好的一点我没有看到你的观点。我用更新了我的代码,而(promises.length
例如,一次最多50个承诺的池大小,但通过*iterRequests
的请求超过50个,一个人如何处理所有承诺?一个人是否通过让{value,done}=iterPromises.next()达到done
?第一批调用从while
循环开始,该循环通常在达到池大小时结束,但当这50个承诺中的一个解决时,再次调用相同的函数nextPromise
(通过然后),并一直持续到it完成<
const fetchData = async () => {
function * iterRequests() {
for (let macAddress of macAddresses) {
yield axios.get("/ipdn/" + macAddress, { timeout: 10000 });
}
}
return poolPromises(iterRequests(), 50).then(setData);
}