Javascript 收集forEach中承诺内生成的承诺

Javascript 收集forEach中承诺内生成的承诺,javascript,mongodb,promise,Javascript,Mongodb,Promise,我想显示到mongodb的迁移操作的进度 脚本如下所示: let promises = []; mylist.forEach(idx => { myCollection.find({id: idx}).toArray().then(msgs => { promises.push(myCollection2.insertMany(msgs.map(msg => ({ msg: msg, otherFields

我想显示到mongodb的迁移操作的进度

脚本如下所示:

let promises = [];
mylist.forEach(idx => {
    myCollection.find({id: idx}).toArray().then(msgs => {
        promises.push(myCollection2.insertMany(msgs.map(msg => ({
            msg: msg,
            otherFields: others
        }))))
    })
});

// function to display the progress:
allProgress(promises,
  (p) => {
     console.log(`% Done = ${p.toFixed(2)}`);
});
function allProgress(proms, progress_cb) {
    let d = 0;
    progress_cb(0);
    proms.forEach((p) => {
      p.then(()=> {    
        d ++;
        progress_cb( (d * 100) / proms.length );
      });
    });
    return Promise.all(proms);
}
这不起作用,因为调用
allProgress()
时,
promises
为空

在调用
allProgress()
之前,如何正确收集所有承诺


更新

在生产MCVE的过程中,我提出了

let promissions=[];
[1,2,3]。forEach(idx=>{
测试(1000)。然后(承诺。推动(测试(10000));
});
console.log(promises.length);
//用于显示进度的函数:
所有进展(承诺,
(p) =>{
log(`%Done=${p.toFixed(2)}`);
});
功能测试(ms){
返回新承诺((解决)=>{
设置超时(()=>{
log(`Waited${ms}`);
解决();
},ms);
});
}
功能所有进度(proms、progress\u cb){
设d=0;
进展情况(0);
(p)=>{
p、 然后(()=>{
d++;
进度(d*100)/项目长度;
});
});
返回承诺。全部(proms);
}
.find()函数是异步的,因此当您仍在查找元素时,forEach循环本身将继续运行。最后,您将等待您的.find()

您可以在.then()回调中检查当前forEach项的索引,如果您位于最后一项,则我们知道所有承诺都已返回。所以在那里调用allProgress函数

这应该给我们留出足够的时间等待一切的到来。此外,通过对照索引进行检查,我们知道我们只会在完成时调用您的AllPromissions函数。每个forEach循环不会发生多次

let promissions=[];
mylist.forEach((idx,索引)=>{
myCollection.find({id:idx}).toArray().then(msgs=>{
promises.push(myCollection2.insertMany(msgs.map)(msg=>({
味精:味精,,
其他领域:其他
}))));
如果((索引+1)==mylist.length){
//用于显示进度的函数:
所有进展(承诺,(p)=>{
log(`%Done=${p.toFixed(2)}`);
});
}
})
});
功能所有进度(proms、progress\u cb){
设d=0;
进展情况(0);
(p)=>{
p、 然后(()=>{
d++;
进度(d*100)/proms.length;
});
});
返回承诺。全部(proms);
}
myCollection.find({id:idx})是异步操作。 所以你可以这样说:

let promises = [];
mylist.forEach(idx => {
    myCollection.find({id: idx}).toArray().then(msgs => {
       promises.push(myCollection2.insertMany(msgs.map(msg => ({
           msg: msg,
           otherFields: others
       }))))
      allProgress(promises,
        (p) => {
            console.log(`% Done = ${p.toFixed(2)}`);
      });
  })
});
function allProgress(proms, progress_cb) {
   let d = 0;
    progress_cb(0);
   proms.forEach((p) => {
     p.then(()=> {    
       d ++;
       progress_cb( (d * 100) / proms.length );
     });
   });
   return Promise.all(proms);
}

这将导致在forEach的每个循环中调用所有承诺,这可能会导致相同的承诺被多次执行。为什么不使用
map
而不是
forEach
+
push
?这也将防止你的错误,注意到有轻微的打字错误,应该是索引+1。在示例中已修复。