【问题标题】:NodeJS : callback and Async callsNodeJS:回调和异步调用
【发布时间】:2017-08-23 19:51:07
【问题描述】:

我盯着屏幕看太久了,似乎无法弄清楚... 基本上我使用猫鼬做 3 个查询,每个查询都基于另一个查询的结果。由于某种原因,父调用在孩子完成任务之前就完成了。这是我的代码,为什么父母不等孩子完成工作才继续?我怎样才能使代码按我的意愿运行:-)

有人告诉我要使用 Promise,但它看起来使用起来很复杂,我认为使用回调足以处理异步调用还是我错了?

var ctr = 0; // counter 1
var ct2 = 0; // counter 2

//Array to be used for the header of the csv file
var mainArr = [["Personeelsnummer", "Chauffeur", "Week 1", "Week 2", "Week 3", "Week 4"]];

    // Find all users in the database
    User.find({}).exec(function (err, users){
        // forEach user, push some basic data into tempArr
        // and lookup planned weeks (geplandeWeken) using another mongoose function
        users.forEach(function(user){
            var tempArr = [];
            tempArr.push(user.personeelsnummer);
            tempArr.push(user.fullName);

            user.geplandeWeken.forEach(function(week1){
                Week.findById(week1, function(err, foundWeek){
                    tempArr.push(foundWeek.week);

                    ctr++;
                    if(ctr === user.geplandeWeken.length){
                        mainArr.push(tempArr);
                        console.log(mainArr);
                    }
                });
            });
            ct2++;
        }); 

        if(ct2 === users.length){
            console.log(ct2);
            csv.write(mainArr, {headers:true}).pipe(res);           
        }       
    });

长话短说:users.forEachuser.geplandeWeken.forEach 能够完成工作之前完成。在收集任何数据并将其存储到 csv 文件之前,会将 csv 文件发送给用户。

【问题讨论】:

  • 坚持承诺,直到你理解它们。它会带你到另一个层次。然后,学习 async/await。下面的例子是很好的方向。

标签: node.js mongodb express mongoose callback


【解决方案1】:

首先,您已经同步编写了代码,这就是为什么它不等待您的依赖关系解决并在之后继续。

为此,您需要使用回调或承诺。我更喜欢后者,因为编写女巫回调时一些复杂的代码可能会导致回调地狱。

关于promise的参考:Promises

因此,根据您的要求,您可以使用如下承诺: 通过 npm 安装 bluebird(我更喜欢它,你也可以使用任何其他包),并在你的主文件中使用它作为

var Promise = require("bluebird");
mongoose.Promise = Promise;

要使用 Promise 制作自定义函数,您可以使用以下

function sample(required Params){
  return new Promise(function(resolve,reject){
   //do things you want to perform
   resolve(params you want to sendBack)//if everything has worked correctly
   reject(params you want to sendBack)// if something goes wrong
  };
}

根据你的代码,我已经用我能理解的最好的承诺对其进行了修改

var ctr = 0; 
var ct2 = 0;

var mainArr = [["Personeelsnummer", "Chauffeur", "Week 1", "Week 2", "Week 3", "Week 4"]];
User.find({})
.then(function(users){
  for(user in users){
   var tempArr = [];
   tempArr.push(user.personeelsnummer);
   tempArr.push(user.fullName);
   for(week1 in user.geplandeWeken){
    Week.findById(week1)
    .then(function(foundWeek){
      tempArr.push(foundWeek.week);
      ctr++
      if(ctr === user.geplandeWeken.length){
          mainArr.push(tempArr);
          console.log(mainArr);
      }
    });
   }
   if(ct2 === users.length){
      console.log(ct2);
      csv.write(mainArr, {headers:true}).pipe(res);
   }
 }
})
.catch(function(err){
 //this is the common error handler
 //code for handling error
});

而且就个人而言,因为您使用的是基于 json 的语言,即 javasacript,请尝试将您的 tempArr 用作 json,因为如果您需要向 tempArr 变量添加一些新值或您决定在未来添加一些新值,它将为您提供更多的灵活性和更少的变化打乱存储在变量中的值的顺序

var tempArr = {};
tempArr[keyName]=keyValue;

并像这样访问它 tempArr.keyName;

要将 for 循环转换为异步循环,请使用以下方法

function asyncFor(i){
   if(i < users.length){
     let user = users[i];
     //perform your rest of the actions and execute the last statment
     asyncFor(i++);
   }else{
     return;
   }
}asyncFor(0);

希望这能回答您的问题

【讨论】:

  • 感谢您的帮助,我在正确的轨道上,但在此代码块中仍有一个问题。在代码部分“for(user in users)”中有另一个for循环“for(user.geplandeWeken中的week1)”我怎样才能让第一个for循环等到第二个for循环的回调完成?
  • 非常冗长的答案,但你的代码并没有解决他的问题
【解决方案2】:

Week.findById 是异步的。它不会阻止代码执行,并继续执行下一条指令。

如果您需要等待许多异步任务完成后再继续,那么您可以使用Promises

var userPromises = users.map(user => {
    return new Promise((resolve, reject) => {
        // do something async
        // resolve(value) when complete 
    })
})

Promise.all(userPromises).then(results => {
    // do something with results
})

【讨论】:

  • 阅读 MDN 关于 promises 并做所有的例子。
猜你喜欢
  • 2017-05-15
  • 2014-05-21
  • 1970-01-01
  • 2018-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-08
相关资源
最近更新 更多