0

i have a little problem whit translation of a PHP sync code to Node.

PHP

$bodies = getBodystyles();
foreach($bodies as $b) {
  $aCar['body'] = $b['Body'];
  $code = getCode($aCar);
  $promo = checkPromotionByCarID($code['Car']);
}

i'll try to convert it in this way:

NODE

db.getBodystyles(function(err, bodies){
  for (b in bodies) {
    console.log(bodies[b]);
    var aCar = Common.ConfiguratorDefault;
    db.getCode(aCar, function(err, code){
      console.log(code);
      bodies[b].aCar = aCar;
      bodies[b].code = code;
      // checkPromotionByCarID here?
    });
  }
  options.bodies = bodies;
  showView(options);
});

but with this code showView run before getCode calling finish.

what the right approach to do that? any help would be appreciated

UPDATE I see this question is marked as duplicated. The suggested duplicate are here However the question proposed doesn't solve my problem. I need to perform a function (showView) after loop finish and after all asynchronous calls inside the loop are finished.

i start from a Select on DB and for each element of result i need to perform other two queries. Only after that queries are finished i need to perform my function and i doesn't understand how do that, and the question suggested doesn't solve my need.

Community
  • 1
  • 1
Zauker
  • 2,344
  • 3
  • 27
  • 36
  • Pointy and Mritunjay were pointing at the [infamous loop issue](http://stackoverflow.com/q/1451009/1048572) that your `db.getCode` callbacks have. – Bergi Sep 11 '14 at 22:59
  • To get `showView` called *after all callbacks* you typically will use a helper library like [tag:async.js] or [tag:promises], as handwriting the logic is tedious and errorprone. – Bergi Sep 11 '14 at 23:01

1 Answers1

0

as suggested, the solution to my problem is obtained with the libraries Async or Rsvp.

Below are two possible solutions:

ASYNC

Using Async.js

db.getBodystyles(function(err, bodies){
    async.each(bodies, function( b, callback) {
        var aCar = Common.ConfiguratorDefault;
        aCar.body = b.Body;
        db.getCode(aCar, function(err, code){
            if (err){
                callback(err);
            }else{
                b.aCar = aCar;
                b.code = code;
                db.checkPromotionByCarID(code.Car, function(err, promo){
                    if (err){
                            callback(err);
                    }else{
                            b.promo = promo;
                            callback();
                    }                           
                });
            }
        });
    },function(err){
        if( err ) {
            console.log('A file failed to process');
            res.render('500');
        } else {
            console.log('All files have been processed successfully');
            options.bodies = bodies;
            showView(options);
        }
    });
});

RSVP

Using Rsvp.js

db.getBodystyles(function(err, bodies){
  var promises = bodies.map(function(b) {
    var aCar = Common.ConfiguratorDefault;
    aCar.body = b.Body;
    var promise = new RSVP.Promise(function(resolve, reject) {
      db.getCode(aCar, function(err, code){
        if(err) reject(err);
        b.aCar = aCar;
        b.code = code;
        db.checkPromotionByCarID(code.Car, function(err, promo){
            if(err) reject(err);
            b.promo = promo;
            resolve();
        });
      });
    });
    return promise;
  };

  RSVP.all(promises).then(function() {
    options.bodies = bodies;
    showView(options);
  }).catch(function(err) {
    throw err;
  });
});
Zauker
  • 2,344
  • 3
  • 27
  • 36