kuba12 kuba12 - 3 months ago 9
Node.js Question

How to make for loop to do all functions before next iteration in Node.js

everyone. I am doing an application that adds and updates fileds in database.
My problem is that my loop continues even though database updating calls still not yet successfully finished.
How can I manage to make for loop wait unit those functions finish before continuing the loop?

Any help will be appreciated.

Here is this piece of code:

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

Answer

I advise using some library when you need to do asynchronous things. I wrote a small example based in your code using when, you can see all methods here

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

You also can use native promises: Promise.all