javascript回调函数提前竞争

时间:2014-01-19 23:47:21

标签: javascript node.js

伙计们,我有以下for循环,其中我从另一个模块调用vehicles.alertsVid函数,它返回每个车辆的状态。结果确实到了,但稍后,并没有得到适当的补充。

写这个的正确方法是什么,因此主循环不会提前竞争,temp.status及时写入? :)

for (var i = vehiclesStuff.length - 1; i >= 0; i--) {
var temp = {};
temp.name = vehiclesStuff[i].nickname.S;
temp.plate = vehiclesStuff[i].plate.S;
temp.base = vehiclesStuff[i].base.S;
temp.vin = vehiclesStuff[i].vin.S;
temp.vid = vehiclesStuff[i].vid.S;

var myfunc = function(t,results,done){return function(){
    console.log ("ALERTS",results);
    t.status = results.toString();
    done();
}};

vehicles.alertsVid(temp.vid, myfunc(temp));

vehicleArray.push(temp);
};
callback()

3 个答案:

答案 0 :(得分:2)

for (var i = vehiclesStuff.length - 1; i >= 0; i--) {
    var temp = {}
    temp.name = vehiclesStuff[i].nickname.S;
    temp.plate = vehiclesStuff[i].plate.S;

    var myfunc=function(t,results,done){return function(){
        console.log ("ALERTS",results);
        t.status = results.toString();
        done();
    }};


    vehicles.alertsVid(temp.vid, myfunc(temp,results, done));

    vehicleArray.push(temp);
};

当你调用内部函数时,变量在调用时被绑定到调用堆栈。因此,回调函数不会“提前竞争”。

请注意,该函数本身返回一个函数,因此返回双嵌套。我的一个签名。 =)

答案 1 :(得分:2)

您应该熟悉闭包的概念。闭包是捕获任何给定评估/执行链的上下文的有效方式。

function callbackClosure(temp){
  return function(results, done){
    console.log ("ALERTS",results);
    temp.status = results.toString();
    done();
  };
}

for (var i = vehiclesStuff.length - 1; i >= 0; i--) {
  var temp = {};
  temp.name = vehiclesStuff[i].nickname.S;
  temp.plate = vehiclesStuff[i].plate.S;
  temp.base = vehiclesStuff[i].base.S;
  temp.vin = vehiclesStuff[i].vin.S;
  temp.vid = vehiclesStuff[i].vid.S;

  vehicles.alertsVid(temp.vid, callbackClosure(temp));

  vehicleArray.push(temp);
}

这段代码正在做的是通过返回一个函数来创建一个新的上下文,该函数由callbackClosure执行实例作用于一个特定的传入对象,该对象将保留在其中唯一的范围,直到执行。

这假设你的vehicles.alertsVid执行并在其callBack中返回一个results对象,以及一个done函数。

在此问题中了解有关闭包的详情:How do JavaScript closures work?

答案 2 :(得分:1)

如果您可以控制从车辆调用的alertsVid函数,您可能希望将整个临时对象传递给它,让它处理它而不是temp.vid (这个属性在哪里)无论如何来自?)

这样,您传递相同的对象引用,以便在最终处理时,您将状态添加到右侧temprightTemp)。这样它就可以在callBack中返回正确的temp作为参数。

您正在初始化新对象temp,并添加nameplate。我在vid上看不到temp属性?

此外,如果您想要等到所有temp被处理并且状态正好在您拨打最后一个回叫之前,您可以使用计数器等待它开火。如果您不想这样做,请忽略这些行......(我已经评论过“// callBack handling”)

另外......修复那些分号。 :P

var numProcessed = 0; // callBack handling
var numToProcess = vehiclesStuff.length; // callBack handling

for (var i = vehiclesStuff.length - 1; i >= 0; i--) {
    var temp = {};
    temp.name = vehiclesStuff[i].nickname.S;
    temp.plate = vehiclesStuff[i].plate.S;

    vehicles.alertsVid(temp, function (rightTemp, results, done) {
        console.log ("ALERTS",results);
        rightTemp.status = results.toString();            
        done();
        processedTemp(); // callBack handling
    })

    vehicleArray.push(temp);
}

// callBack handling
function processedTemp(){
  numProcessed++;
  if(numProcessed === numToProcess) callBack();
}

你的vehicles.alertsVid函数将如下所示:

vehicles.alertsVid = function(temp, callBack){
  ...
  callBack(temp, results, done); // using the same temp (object reference) that was passed in!!!
};

这是假设您可以控制vehicles.alertsVid功能。