Node.js-希望对循环中的方法进行5次并行调用

Node.js-希望对循环中的方法进行5次并行调用,node.js,express,async.js,kue,Node.js,Express,Async.js,Kue,我在MongoDB集合中有1000个信息文件。我正在编写一个查询以获取1000条记录,在一个循环中,我正在调用一个函数将该文件下载到本地系统。因此,下载所有1000个文件是一个循序渐进的过程 我希望在下载过程中有一些并行性。在循环中,我想一次下载10个文件,这意味着我想调用下载函数10次,完成10个文件下载后,我想下载下10个文件(这意味着我需要调用下载函数10次) 我如何实现这种并行性,或者有更好的方法来实现这一点 我看到了Kuenpm,但是如何实现这一点呢?顺便说一句,我是从FTP下载的,所

我在MongoDB集合中有1000个信息文件。我正在编写一个查询以获取1000条记录,在一个循环中,我正在调用一个函数将该文件下载到本地系统。因此,下载所有1000个文件是一个循序渐进的过程

我希望在下载过程中有一些并行性。在循环中,我想一次下载10个文件,这意味着我想调用下载函数10次,完成10个文件下载后,我想下载下10个文件(这意味着我需要调用下载函数10次)

我如何实现这种并行性,或者有更好的方法来实现这一点

我看到了
Kue
npm,但是如何实现这一点呢?顺便说一句,我是从FTP下载的,所以我使用
基本FTP
npm进行FTP操作。

该库在这方面功能非常强大,一旦您了解了基本知识,也非常容易

我建议你使用它,这样你的应用程序就不必担心一批十个文件的循环,它只会让十个文件同时下载

var files = ['a.txt', 'b.txt']
var concurrency = 10;

async.eachLimit(files, concurrency, downloadFile, onFinish);


function downloadFile(file, callback){

  // run your download code here
  // when file has downloaded, call callback(null)
  // if there is an error, call callback('error code')

}

function onFinish(err, results){

  if(err) {
    // do something with the error
  }

  // reaching this point means the files have all downloaded

}
异步库将并行运行
downloadFile
,从
files
列表中向每个实例发送一个条目,然后当列表中的每个项目都完成时,它将调用
onFinish

库在这方面非常强大,并且一旦您了解了基本知识,该库也非常简单

我建议你使用它,这样你的应用程序就不必担心一批十个文件的循环,它只会让十个文件同时下载

var files = ['a.txt', 'b.txt']
var concurrency = 10;

async.eachLimit(files, concurrency, downloadFile, onFinish);


function downloadFile(file, callback){

  // run your download code here
  // when file has downloaded, call callback(null)
  // if there is an error, call callback('error code')

}

function onFinish(err, results){

  if(err) {
    // do something with the error
  }

  // reaching this point means the files have all downloaded

}

异步库将并行运行
downloadFile
,从
files
列表中向每个实例发送一个条目,然后当列表中的每个项目都完成时,它将调用
onFinish
,而不查看您的实现,我只能提供一个通用答案

假设您的下载函数接收到一个fileId,并返回一个承诺,该承诺在所述文件完成下载时解析。对于这个POC,我将模拟它,并承诺在200到500毫秒后解析为文件名

function download(fileindex) {
  return new Promise((resolve,reject)=>{ 
    setTimeout(()=>{ 
      resolve(`file_${fileindex}`);
    },200+300*Math.random());
  });
}
您有1000个文件,并希望在100次迭代中下载它们,每次迭代10个文件

让我们把东西封装起来。我将声明一个函数,该函数接收起始ID和大小,并返回
[N…N+size]
ID

function* range(bucket, size=10) {
    let start = bucket*size, 
        end=start+size;
    for (let i = start; i < end; i++) {
        yield i;
    }
}
A在这一点上,
bucket
的内容是:

 [
   [file0 ... file9]
   ...
   [file 990 ... file 999]
 ]
然后,使用
for..of
(支持异步)迭代存储桶

在每次迭代中,使用
Promise.all
将10个调用排入
download

async function proceed() {
    for await(let bucket of buckets) { // for...of
       await Promise.all(bucket.reduce((accum,fileindex)=>{
           accum.push(download(fileindex)); 
           return accum; 
       },[]));
    }
}
让我们看一个正在运行的示例(只有10个bucket,我们在这里都很忙:D)

函数下载(文件索引){
返回新承诺((解决、拒绝)=>{
let file=`file_${fileindex}`;
设置超时(()=>{
解决(文件);
},200+300*Math.random());
});
}
功能*范围(铲斗,尺寸=10){
让我们开始=桶*大小,
结束=开始+大小;
for(让i=start;i{
返回[…范围(桶,10)];
});
异步函数继续(){
假设bucketNumber=0,
timeStart=performance.now();
等待(让桶中的桶){
让startingTime=Number((performance.now()-timeStart)/1000).toFixed(1).substr(-5),
结果=等待承诺.all(bucket.reduce)(累计、文件索引)=>{
累计推送(下载(文件索引));
返回累计;
}, []));
console.log(
`${startingTime}的下载桶${bucketNumber}`
);
等待结果;
让endingTime=Number((performance.now()-timeStart)/1000).toFixed(1.substr(-5);
console.log(
`${endingTime}的存储桶${bucketNumber++}完成:`,
`[${result[0]}…${result.pop()}]`
);
}
}
document.querySelector(“#继续”).addEventListener('click',继续)

继续
在没有看到您的实现的情况下,我只能提供一个通用的答案

假设您的下载函数接收到一个fileId,并返回一个承诺,该承诺在所述文件完成下载时解析。对于这个POC,我将模拟它,并承诺在200到500毫秒后解析为文件名

function download(fileindex) {
  return new Promise((resolve,reject)=>{ 
    setTimeout(()=>{ 
      resolve(`file_${fileindex}`);
    },200+300*Math.random());
  });
}
您有1000个文件,并希望在100次迭代中下载它们,每次迭代10个文件

让我们把东西封装起来。我将声明一个函数,该函数接收起始ID和大小,并返回
[N…N+size]
ID

function* range(bucket, size=10) {
    let start = bucket*size, 
        end=start+size;
    for (let i = start; i < end; i++) {
        yield i;
    }
}
A在这一点上,
bucket
的内容是:

 [
   [file0 ... file9]
   ...
   [file 990 ... file 999]
 ]
然后,使用
for..of
(支持异步)迭代存储桶

在每次迭代中,使用
Promise.all
将10个调用排入
download

async function proceed() {
    for await(let bucket of buckets) { // for...of
       await Promise.all(bucket.reduce((accum,fileindex)=>{
           accum.push(download(fileindex)); 
           return accum; 
       },[]));
    }
}
让我们看一个正在运行的示例(只有10个bucket,我们在这里都很忙:D)

函数下载(文件索引){
返回新承诺((解决、拒绝)=>{
let file=`file_${fileindex}`;
设置超时(()=>{
解决(文件);
},200+300*Math.random());
});
}
功能*范围(铲斗,尺寸=10){
让我们开始=桶*大小,
结束=开始+大小;
for(让i=start;i{
返回[…范围(桶,10)];
});
异步函数继续(){
假设bucketNumber=0,
timeStart=performance.now();
等待(让桶中的桶){
让startingTime=Number((performance.now()-timeStart)/1000).toFixed(1).substr(-5),
结果=等待承诺.all(bucket.reduce)(累计、文件索引)=>{
累计推送(下载(文件索引));
返回累计;
}, []));
console.log(
`${startingTime}的下载桶${bucketNumber}`
);
等待结果;
让endingTime=Number((performance.now()-timeStart)/1000).toFixed(1.substr(-5);
console.log(
`${endingTime}的存储桶${bucketNumber++}完成:`,
`[${result[0]}…${result.pop()}]`
);
}
}
document.querySelector(“#继续”).addEventListener('click',继续)