关于node.js:javascript回调函数前进

javascript callback function racing ahead

本问题已经有最佳答案,请猛点这里访问。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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()


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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函数。

在这个问题上了解有关闭包的更多信息:JavaScript闭包如何工作?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);
};

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

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


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

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

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

此外,如果您想要等到所有temp处理完并且状态正好,那么在调用最终回调之前,您可以使用计数器等待它触发。如果您不想这样做,请忽略这些行...(我已经评论过"// callBack handling")

还...修复那些分号。 :P

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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函数看起来像:

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

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