如何使循环在Node.js中的下一次迭代之前完成所有函数

时间:2015-11-04 23:02:28

标签: node.js mongodb for-loop asynchronous

大家。我正在做一个在数据库中添加和更新文件的应用程序。 我的问题是,即使数据库更新调用仍未成功完成,我的循环仍在继续。 如何在继续循环之前设置为循环等待单元完成这些功能?

任何帮助将不胜感激。

以下是这段代码:

for(i = 0; i < treatments.length; i++) {
    collection3.find({"_id": parseInt(treatments[i])}).toArray(function(err, results) {
    if(results[0].maxPrice < parseInt(treatmentsPrices[i])){
        collection3.update({"_id": parseInt(treatments[i])}, {"maxPrice": parseInt(treatmentsPrices[i])}, function(err, success) {
            counter++;
            console.log(err);
        });
    }
    if(results[0].minPrice > parseInt(treatmentsPrices[i])){
        collection3.update({"_id": parseInt(treatments[i])}, {"minPrice": parseInt(treatmentsPrices[i])}, function(err, success) {
            console.log(err);
        });
    }
    collection3.update({"_id": parseInt(treatments[i])}, {$addToSet: {"doctors": parseInt(doctorId)}}, function(err, success) {
        console.log(err);
    });
    collection3.update({"_id": parseInt(treatments[i])}, {$addToSet: {"hospitals": parseInt(hospitals[i])}}, function(err, success) {
        console.log(err);
    });
    if(newHospitalName != null) {
        collection3.update({"_id": parseInt(treatments[i])}, {$addToSet: {"hospitals": parseInt(hospitalId)}}, function(err, success) {
            console.log(err);
        });
    }
    });                         
}

2 个答案:

答案 0 :(得分:2)

我建议您在需要执行异步操作时使用某些库。 我使用when在您的代码中编写了一个小示例,您可以看到所有方法here

&#13;
&#13;
var when = require('when');
var promises = [];

var treatmentsUpdater = function (opts) {
  var treatments = opts.treatments;
  var treatmentsPrices = opts.treatmentsPrices;
  var doctorId = opts.doctorId
  var hospitals = opts.hospitals;
  var hospitalId = opts.hospitalId

  collection3.find({"_id": parseInt(treatments[i])}).toArray(function(err, results) {
    if(results[0].maxPrice < parseInt(treatmentsPrices[i])){
      collection3.update({"_id": parseInt(treatments[i])}, {"maxPrice": parseInt(treatmentsPrices[i])}, function(err, success) {
        counter++;
        console.log(err);
      });
    }
    if(results[0].minPrice > parseInt(treatmentsPrices[i])){
      collection3.update({"_id": parseInt(treatments[i])}, {"minPrice": parseInt(treatmentsPrices[i])}, function(err, success) {
        console.log(err);
      });
    }
    collection3.update({"_id": parseInt(treatments[i])}, {$addToSet: {"doctors": parseInt(doctorId)}}, function(err, success) {
      console.log(err);
    });
    collection3.update({"_id": parseInt(treatments[i])}, {$addToSet: {"hospitals": parseInt(hospitals[i])}}, function(err, success) {
      console.log(err);
    });
    if(newHospitalName != null) {
      collection3.update({"_id": parseInt(treatments[i])}, {$addToSet: {"hospitals": parseInt(hospitalId)}}, function(err, success) {
        console.log(err);
      });
    }
  });
}

for(i = 0; i < treatments.length; i++) {
  var opts = {
    treatments: treatments[i],
    treatmentsPrices: treatmentsPrices[i],
    doctorId: doctorId,
    hospitals: hospitals[i],
    hospitalId: hospitalId
  }
  promises.push(treatmentsUpdater(opts))   
}

when.all(promises).then(function () {
  console.log("The database has been updated")
})
&#13;
&#13;
&#13;

您还可以使用原生承诺:Promise.all

答案 1 :(得分:1)

我会毫不留情地宣传我们自己的名为Coastline的图书馆。代码看起来像这样。

CL.each(treatments, function* (treatment, i) {
  
  var results = yield collection3.find({"_id": parseInt(treatment)}).toArray(CL.cb());
  
  if (results[0].maxPrice < parseInt(treatmentsPrices[i])) {
    CL.bg(collection3.update({"_id": parseInt(treatment)}, {"maxPrice": parseInt(treatmentsPrices[i])}, CL.cb()));
  }
  if(results[0].minPrice > parseInt(treatmentsPrices[i])) {
    CL.bg(collection3.update({"_id": parseInt(treatment)}, {"minPrice": parseInt(treatmentsPrices[i])}, CL.cb()));
  }
                       
  CL.bg(collection3.update({"_id": parseInt(treatment)}, {$addToSet: {"doctors": parseInt(doctorId)}}, CL.cb()));
  
  CL.bg(collection3.update({"_id": parseInt(treatment)}, {$addToSet: {"doctors": parseInt(doctorId)}}, CL.cb()));
  
  CL.bg(collection3.update({"_id": parseInt(treatment)}, {$addToSet: {"hospitals": parseInt(hospitals[i])}}, CL.cb()));
  
  if(newHospitalName != null) {
    CL.bg(collection3.update({"_id": parseInt(treatment)}, {$addToSet: {"hospitals": parseInt(hospitalId)}}, CL.cb()));
  }
  
});

在运行下一个CL.bg()迭代之前,库将等待所有CL.each()次调用完成。您可以将CL.bg()替换为yield,以便在迭代内按顺序执行所有内容。