0

I want to use async to make node.js work something in order, first query two rates from mongodb,then use these rates to compute two new rate:

async.series([
    function(callback){
        db.collection('heros',function(err,collection){
            if(err){
                console.log(err);
            }
            if(!err){
                console.log("2 collection fetched!");
                collection.findOne({'id':win},function(err,result){
                    if (err) throw err;
                    rate1=result.rate;
                    console.log("win-rate:"+rate1);
                });
                collection.findOne({'id':lose},function(err,result){
                    if (err) throw err;
                    rate2=result.rate;
                    console.log("lose-rate:"+rate2);
                });         
            }
        });
        callback(null);

    }, function(callback){   
        var Ea= 1/(1+Math.pow(10,(rate2-rate1)/400));
        var Eb= 1/(1+Math.pow(10,(rate1-rate2)/400));
        var ra= rate1+16*(1-Ea);
        var rb= rate2+16*(0-Eb);
        console.log("ra:"+ra);
        console.log("rb:"+rb);
        callback(null);
    },
        function(callback){   
    db.collection('heros',function(err,collection){
        if(!err){
        collection.update({'id':win},{$set:    {rate:ra}},function(err,result){
          if(err) throw err;
          if(!err){
            console.log("update successful");
          }
          });
          collection.update({'id':lose},{$set:{rate:rb}},function(err,result){
          if(err) throw err;
          if(!err){
            console.log("update successful");
        }
        });

            }

    });
    callback(null);
}
]);

but when I run it, it shows error messages:

ReferenceError: ra is not defined

it seems that nodejs jumps to computing or updating without waiting for the query complete.

4

1 回答 1

5

You're declaring the variables like ra inside of a function block, so they're scoped to that function and unavailable elsewhere. You'd need to put them somewhere more accessible. For example, you could put them in a global variable:

var ra;

async.series([ ... ]);

Further, when you use series, you should call the callback function only when all of the work for that step has completed.

For example, one task should look like this:

db.collection('heros',function(err,collection){
        if(err){
            console.log(err);  // log the error
            callback(err);     // call the async call back with the error
            return;            // stop 
        }
        console.log("2 collection fetched!");
        collection.findOne({'id':win},function(err,result){
            if (err) { callback(err); return; } // again, handle error
            rate1 = result.rate;                // grab results
            console.log("win-rate:"+rate1);     // log
            callback(null, rate1);              // now indicate complete by calling
        });
    });

As you've got multiple async function calls within a single task, you may want to split them to multiple tasks or consider using the parallel function as well. You could even use parallel within one of the other tasks in the series call to handle the case where you have two findOne calls that need to be made.

于 2013-08-28T01:19:57.517 回答