【问题标题】:Can a node promise chain fail to execute synchronously?节点承诺链是否无法同步执行?
【发布时间】:2019-07-14 23:08:54
【问题描述】:

如果我有如下示例的一系列承诺/函数,那么函数是否仍然可能会乱序解析?我有一个功能是猫鼬查询和更新,然后另一个将数据发送到视图。我的视图正在加载,但未反映 mongoose 查询结果的正确结果。

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));

这是我整理的代码:就像“res.json({status: 200, data: result});”在 mongoose find 完成之前执行?

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));

});

【问题讨论】:

  • 不,函数会依次解析。如果您添加实际代码会更好地回答。
  • 不,它们将按顺序解决,因为一旦解决了第一个问题,您就会调用第二个,一旦解决了第二个,您就会调用第三个。所以它会按顺序运行,除非有错误,因为如果有它会中止。另外,如果您想避免链接这些承诺,可以使用 async await 以正确的顺序获取它们。
  • 谢谢你们,我已经添加了我整理的代码。在 mongoose 查询完成之前,promise 链有没有什么方法可以结束?
  • 'Invoicestatus.update' 函数的本质是什么,如果它返回一个承诺,那么你以错误的方式使用它。第二件事不要 console.log 你的错误,使用 reject(error)
  • Ivoicestatus.update 用于更新集合 Invoicestatus 中的各个字段值。看起来有问题吗?

标签: node.js promise


【解决方案1】:

问题出在循环的 saveinvprodcount 方法中,函数将在执行 Invoicestatus.update 函数之前解决,

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);
    });
};

首先promisify update 函数,然后使用一个数组来保存promises,你可以使用promis.all 来一次执行所有promises。见下文

 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();
        });
     });
   };

【讨论】:

  • 非常感谢,Ganesh,我会试试这个!
  • @B.sabz 让我知道它是否有效或出现任何其他问题
  • 谢谢 Ganesh,那个工作的人!唯一的事情是“promises.push(updateData(invprodcount(ok)));”应该是“promises.push(updateData(invprodcount[ok]));”。我对 getinvprodsprice 做了同样的事情,现在是 100%。非常感谢,先生。
【解决方案2】:

是的。你可以做。通过使用Promise.all([promise1, promise2, promise3]) 让它们异步运行并立即获得结果。但是,在这种情况下,第一次调用的结果是输入,您需要在运行第二次之前等待它。因此,您必须按顺序运行(因为业务逻辑,而不是语言的性质。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    相关资源
    最近更新 更多