简体   繁体   中英

Can a node promise chain fail to execute synchronously?

If I have a sequence of promises/function as example below, is it still possible that functions would resolve out of sequence? I have one function that is a mongoose query and update then another sends the data to a view. My view is loading but is not reflecting the correct results of the mongoose query results.

let function_one(data) = function(){
  return new Promise( function(resolve, reject) {  
    {do stuff...    
      resolve('howdy');
    }
  });
};

let function_two(some_data) = function(){
  return new Promise( function(resolve, reject) {  
    {  do stuff...    
    resolve('howdy');
    }
  });
};  

let function_three(some_data) = function(){
  return new Promise( function(resolve, reject) {  
    {do stuff...    
      resolve('howdy');
    }
  });
};  

let function_four(some_data) = function(){
  return new Promise( function(resolve, reject) {  
    {do stuff...    
      resolve('howdy');
    }
  });
};  

function_one(data).then(function(result){
  return function_two(result);
}).then(function(result){
  return function_three(result);
}).then(function(result){
  return function_four(result);
}).then(function(result){
  console.log(result);
}).catch(err => console.log("Caught " + err));

Here's the code I have put together: It is as if "res.json({status: 200, data: result});" is being executed before the mongoose find completes?

let gettheinformation =  function(invoicelist3){
    return new Promise(  function(resolve, reject) {
        // console.log(invoicelist3);
            Product.aggregate([
                {
                    $match: {
                        Priced: true
                    }
                }
                ,
                {
                    $group: {
                        _id: "$Invoice",
                        pricedcount: {$sum: 1}
                    }
                }
            ], function (err, result) {
                if (err) {
                    console.log(err);
                } else {
                    resolve(result);
                }
            });
    });
};


let getinvprodspriced =  function(invlist){
    return new Promise(  function(resolve, reject) {
           // console.log(invlist);
        for(var oo = 0; oo < invlist.length; oo++){
        Invoicestatus.update({Invoice:invlist[oo]._id}, {Noofitemspriced: invlist[oo].pricedcount}, {upsert: true},  function (err) {}); 
        }
        resolve(invlist);
        });
};

let getinvprodcount = function(invprodcount){
        return new Promise(  function(resolve, reject) {
    Product.aggregate([
                {
                    $group: {
                        _id: "$Invoice",
                        pradcount: {$sum: 1}
                    }
                }
            ], function (err, result) {
                if (err) {
                    console.log(err);
                } else {
                  // console.log(result);
                    resolve(result);
                }
            });

    });
}


let saveinvprodcount =  function(invprodcount){
    return new Promise(  function(resolve, reject) {
        for(var ok = 0; ok < invprodcount.length; ok++){
        Invoicestatus.update({Invoice:invprodcount[ok]._id}, {Noofitems: invprodcount[ok].pradcount}, {upsert: true},  function (err) {}); 
        }
        resolve(invprodcount);
        });
};

let getarrdocs =  function(result){
    return new Promise( function(resolve, reject) {
        Invoicestatus.find({}, function(err, docs){
          resolve(docs); 
        });       
    });
};

router.get('/fetcharrdata', function(req, res) {


    gettheinformation().then(function(result){
      return getinvprodspriced(result);
    }).then(function(result){
      return getinvprodcount(result);
    }).then(function(result){
      return saveinvprodcount(result);
    }).then( function(result){
      return getarrdocs(result);
    }).then(function(result){


        res.json({status: 200, data: result});


    }).catch(err => console.log("Caught " + err));

});

Yes. You can do. by using Promise.all([promise1, promise2, promise3]) to let them running asynchronously and get the result at once. However, in this case, the result of the first call is the input, you need to wait for it before running the second one. So that, you have to run in sequence (because of the business logic, not the nature of the language.

The problem is in saveinvprodcount methods for loop, function will resolve before execution of Invoicestatus.update function,

let saveinvprodcount =  function(invprodcount){
return new Promise(  function(resolve, reject) {
    for(var ok = 0; ok < invprodcount.length; ok++){
    Invoicestatus.update({Invoice:invprodcount[ok]._id}, {Noofitems: invprodcount[ok].pradcount}, {upsert: true},  function (err) {}); 
    }
 //this will resolve before completion of Invoicestatus.update
    resolve(invprodcount);
    });
};

First promisify update function then use an array to hold promises and You can use promise.all to execute all promises at once. See below

 let saveinvprodcount = function (invprodcount) {
 let promises = [];
 for (var ok = 0; ok < invprodcount.length; ok++) {
     promises.push(updateData(invprodcount[ok]));
 }
 return Promise.all(promises);
 };

 let updateData = function (invProd) {
 return new Promise(function (resolve, reject) {
    Invoicestatus.update({ Invoice: invProd._id },
        { Noofitems: invProd.pradcount }, { upsert: true }, function (err) {
            if (err)
                reject(err);
            else
                resolve();
        });
     });
   };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM