Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用Promise.all处理数千个请求_Javascript_Reactjs_Promise_Axios - Fatal编程技术网

Javascript 如何使用Promise.all处理数千个请求

Javascript 如何使用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

在我的React应用程序中,我有一个组件可以向一个在线服务发送请求,该服务最多可以处理50个请求。我现在收到了一个新的请求,可以执行7000个MAC

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