为什么async.series不尊重我的任务顺序?

时间:2016-07-03 13:49:21

标签: node.js asynchronous async.js

我有一个包含许多文档的集合,例如:

直接航班< => Stops == 0&& Thru_Point == ""

{
    "Orig" : "PTH",
    "Dest" : "GMP",
    "Flight" : 126,
    "Stops" : 0,
    "Seats" : 169,
    "Ops_Week" : 3,
    "Eff_Date" : "2016-04-14",
    "Mkt_Al" : "XX",
    "Thru_Point" : "",
    "Arr_Time" : 1600,
    "Block_Mins" : 230

}

带停止的航班< => Stops == 1&& Thru_Point != ""

{
    "Orig" : "CIM",
    "Dest" : "LKR",
    "Flight" : 7756,
    "Stops" : 1,
    "Seats" : 70,
    "Ops_Week" : 2,
    "Eff_Date" : "2016-04-11",
    "Mkt_Al" : "YY",
    "Thru_Point" : "BHU",
    "Arr_Time" : 140,
    "Block_Mins" : 345 // the elapsed time 
}

每个文件都指的是一个航班,我试图计算每个文件的分数,但我有一个困难,就是当我有一个停止航班我应该计算缩短的时间,直接飞行它&# 39;很简单,经过的时间等于Block_Mins中的值,但对于有停止的航班,我应计算从OrigThru_Point和{{1}的每个段的经过时间转到Thru_point

Dest

我试过这个算法,但我发现自己有相同的值,无论是停止还是直飞!我认为问题来自于mongoose.connection.on("open", function (err) { if (err) throw err; var bulkUpdateOps = Vol.collection.initializeUnorderedBulkOp(), counter = 0; Vol.find({}).lean().exec(function (err, docs) { if (err) throw err; var locals = {}; docs.forEach(function(doc) { locals.c1 = 0.3728 + (0.00454 * doc.Seats); locals.c3 = doc.Ops_Week; if (doc.Stops == 1) { async.series([ // Load doc with first leg first function(callback) { Vol.findOne({ Mkt_Al: doc.Mkt_Al, Orig: doc.Orig, Dest: doc.Thru_Point }).lean().exec(function (err, flight) { if (err) return callback(err); locals.first_leg = flight.Block_Mins; callback(); }); }, // Load second leg doc // (won't be called before task 1's "task callback" // has been called) function(callback) { Vol.findOne({ Mkt_Al: doc.Mkt_Al, Orig: doc.Thru_Point, Dest: doc.Dest }).lean().exec(function (err, flight) { if (err) return callback(err); locals.second_leg = flight.Block_Mins; callback(); }); } ], function(err) { // This function gets called after the // two tasks have called their "task callbacks" if (err) throw err; // Here locals will be populated with `first_leg` // and `second_leg` // Just like in the previous example var total_flight = locals.second_leg + locals.first_leg; locals.c2 = 0.03; locals.c4 = Math.pow((doc.Block_Mins / total_flight), -0.675); }); } else { locals.c2 = 1; locals.c4 = 1; } counter++; console.log(locals); bulkUpdateOps.find({ "_id" : doc._id }).updateOne({ "$set": { "Qsi": (locals.c1 * locals.c2 * locals.c3 * locals.c4) } }); if (counter % 500 == 0) { bulkUpdateOps.execute(function(err, result) { if (err) throw err; bulkUpdateOps = Vol.collection.initializeUnorderedBulkOp(); }); } }); if (counter % 500 != 0) { bulkUpdateOps.execute(function(err, result) { if (err) throw err; console.log(result.nModified); }); } }); }); async.series在其他任务之后也应该在bulkupdate中取代......

提前谢谢你;

1 个答案:

答案 0 :(得分:0)

不保证Async.series按照声明的顺序运行。 每async.js documentation

  

请注意,虽然许多实现保留了对象属性的顺序,但ECMAScript语言规范明确指出

     
    

未指定枚举属性的机制和顺序。

  
     

因此,如果您依赖于执行一系列函数的顺序,并希望它在所有平台上都能运行,请考虑使用数组。

您可以使用async.waterfall()代替,这在您使用的情况下非常有意义。通过对代码进行微调,您可以进行此更改。这是一个例子:

(...)
docs.forEach(function(doc) {            
    locals.c1 = 0.3728 + (0.00454 * doc.Seats);         
    locals.c3 = doc.Ops_Week;

    if (doc.Stops == 1) { 
        async.waterfall([
            // Load doc with first leg first
            function(callback) {
                Vol.findOne({ 
                    Mkt_Al: doc.Mkt_Al,
                    Orig: doc.Orig,
                    Dest: doc.Thru_Point                          
                }).lean().exec(function (err, flight) {
                    if (err) return callback(err);
                    // locals.first_leg = flight.Block_Mins; //no need to save it in locals variable.
                    callback(null, flight.Block_Mins); //passing "first_leg" forward to next function 
                });
            },
            // Load second leg doc 
            // (won't be called before task 1's "task callback" 
            // has been called)
            function(first_leg, callback) {                    
                Vol.findOne({ 
                    Mkt_Al: doc.Mkt_Al,
                    Orig: doc.Thru_Point,
                    Dest: doc.Dest                          
                }).lean().exec(function (err, flight) {
                    if (err) return callback(err);
                    // locals.second_leg = flight.Block_Mins; //same as first leg. No need to save it in a local variable
                    callback(null, first_leg+flight.Block_Mins); //passing "total_flight" forward to next function 
                });
            }
            ], function(err, total_flight) { // This function gets called after the
                if (err) throw err;
                locals.c2 = 0.03;
                locals.c4 = Math.pow((doc.Block_Mins / total_flight), -0.675);                    

        });
    } else {
        (...)