Javascript 循环内的节点和异步调用

Javascript 循环内的节点和异步调用,javascript,php,node.js,asynchronous,Javascript,Php,Node.js,Asynchronous,我在将PHP同步代码翻译到节点时遇到了一个小问题 PHP $bodies = getBodystyles(); foreach($bodies as $b) { $aCar['body'] = $b['Body']; $code = getCode($aCar); $promo = checkPromotionByCarID($code['Car']); } 我将尝试以这种方式转换它: 节点 db.getBodystyles(function(err, bodies){ for

我在将PHP同步代码翻译到节点时遇到了一个小问题

PHP

$bodies = getBodystyles();
foreach($bodies as $b) {
  $aCar['body'] = $b['Body'];
  $code = getCode($aCar);
  $promo = checkPromotionByCarID($code['Car']);
}
我将尝试以这种方式转换它:

节点

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);
});
但是使用此代码showView在getCode调用完成之前运行

正确的方法是什么? 任何帮助都将不胜感激

更新 我看到这个问题被标记为重复。 然而,提出的问题并不能解决我的问题。 我需要在循环完成和循环内所有异步调用完成后执行函数(showView)

我从Select on DB开始,对于结果的每个元素,我需要执行另外两个查询。
只有在查询完成后,我才需要执行我的功能,但我不知道如何执行,而建议的问题并不能解决我的需要。

正如建议的那样,我的问题的解决方案是通过库AsyncRsvp获得的

以下是两种可能的解决方案:

异步

使用

RSVP

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


Pointy和Mritunjay指出了
db.getCode
回调所具有的功能。要在所有回调后调用
showView
,您通常会使用类似或的帮助程序库,因为手写逻辑冗长且容易出错。
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;
  });
});