kuba12
kuba12

Reputation: 265

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

Upvotes: 0

Views: 67

Answers (2)

emilioriosvz
emilioriosvz

Reputation: 1639

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

Upvotes: 2

a sad dude
a sad dude

Reputation: 2825

I will go and shamelessly advertise our own library called Coastline. The code would look something like this.

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

The library will wait for all CL.bg() calls to finish before running the next CL.each() iteration. You can replace CL.bg() with yield for everything to execute in sequence inside the iteration.

Upvotes: 1

Related Questions