简体   繁体   English

如何确保在从 Mongoose 中的函数返回之前执行异步调用?

[英]How to ensure an asynchronous call is executed before returning from a function in Mongoose?

I am new to mongoose and in order to prevent ASYNC OF HELL I came Across an npm package called async .我是 mongoose 的新手,为了防止 ASYNC OF HELL,我遇到了一个名为async的 npm 包。 I have used the async.series of the async npm package and my code looks in the given format given below我使用了async npm 包的async.series并且我的代码看起来像下面给出的给定格式

var userId=1234
function findUser(callback){
  user.findOne({userId:userId}).exec(function(err,userData){
         //Some Logic
   var schoolId=123;
   var schoolName=findSchool(123);     
   findStudents(schoolName);

   var schoolId=1234;
   var schoolName=findSchool(123);     
   findStudents(schoolName);

   callback(null);
  });
}

function findSchool(schoolId){
 school.findOne({schoolId:schoolId}).exec(function(err),schoolDetails){
    //Some Logic  
  });
    var schoolName="XYZ High School"
    return(schoolName);
}

 function findStudents(schoolName){
  student.findOne({schoolName:schoolName}).exec(function(err),studentDetails{
    //Some Logic  
  });
 }

 async.series([findUser],function(err){
     // for Error Handling
    }

Here I am using an async series function to prevent the ASYNC of HELL.这里我使用了一个 async series 函数来防止 HELL 的 ASYNC。 I am calling findUser function in the async series call which is find the user details from my User model using the userId and then I am calling the findSchool function inside the findUser function which finds school details for the given SchoolId in School model.我打电话findUser在异步调用系列是找到我的用户信息功能User使用模型userId ,然后我打电话的findSchool内部功能findUser功能,发现对于给定的学校细节SchoolIdSchool模型。 Once the function returns the call I am trying to find the students based on a particular schoolName using the findStudents function on the Student model.一旦函数返回调用,我将尝试使用Student模型上的findStudents函数根据特定schoolName findStudents Student

The process is repeated for a different schoolId .对不同的schoolId重复该过程。 My Issue comes when I call the findSchool function.当我调用findSchool函数时,我的问题就出现了。 Since it has a asynchronous call ( findOne ) on the school model, I am able to return the value of the schoolName even before the findOne is completed for the model.由于它在school模型上有一个异步调用 ( findOne ),因此即使在模型的findOne完成之前,我也能够返回schoolName的值。

Is there a way to ensure that the given function findSchool doesn't return the value of the schoolName until the school.findOne() has completed successfully?有没有一种方法,以确保给定函数findSchool不返回的值schoolName直到school.findOne()已成功完成? Just to add more clarity I don't want to my return statement inside the findOne of the findSchool function.我想补充更清晰,我不希望里面我return语句findOne的的findSchool功能。

Async.each or async.waterfall should do the trick, I think.我认为 Async.each 或 async.waterfall 应该可以解决问题。

The main thing here is that you're using return statements in your async functions, which will return before the async function has actually completed, and thus they won't pass along what you need.这里的主要问题是您在异步函数中使用 return 语句,它将在异步函数实际完成之前返回,因此它们不会传递您需要的内容。

You have to use async functions and callbacks for this.您必须为此使用异步函数和回调。 You can still have your functions separated like you want in your code, but you'll have to add callback functions instead of returns.您仍然可以像在代码中一样将函数分开,但是您必须添加回调函数而不是返回函数。

You should still use async but you need async.waterfall for that.你仍然应该使用async但你需要async.waterfall Here is what you need to consider:以下是您需要考虑的事项:

A main method to call your async function:调用async函数的主要方法:

var getInformation = function(){
  async.waterfall([
    //Array of your functions in order, we will be back here later
  ], function (err) {
       if(err){
         console.log(err);
       }else{
         console.log('Everything OK!');
     }
  );
}

Then you need your functions to be async friendly, that means you should use callbacks and give your data from one function to another.然后你需要你的函数async友好,这意味着你应该使用回调并将数据从一个函数传递给另一个函数。 Something like this:像这样的东西:

function findUser(callback){
  //Do something
  if('Everything OK'){
    callback(err, yourData); //err should be null if everything is OK and yourData should be the data that you wanna use in your next function. e.g. schoolId 
  }else{
    callback(err); //Something was wrong, "err" should have something different to null
  }
}

function findSchool(callback, schoolId){ //Note that we receive the parameter schoolId here but not in the first function
  //Do something
  if('Everything OK'){
    callback(err, yourData); //err should be null if everything is OK and yourData should be the data that you wanna use in your next function. e.g. schoolName 
  }else{
    callback(err); //Something was wrong, "err" should have something different to null
  }
}

function findStudents(callback, schoolName){
  //Do something
  if('Everything OK'){
    callback(err); //err should be null if everything is OK if this is the last function maybe we don't need to send back more data from here 
  }else{
    callback(err); //Something was wrong, "err" should have something different to null
  }
}

Then you should call your functions in your main method:然后你应该在你的 main 方法中调用你的函数:

var getInformation = function(){
  async.waterfall([
    findUser,
    findSchool,
    findStudents
    //Note that there is no need to tell the functions the parameters they are sending or receiving here
  ], function (err) {
       if(err){
         console.log(err);
       }else{
         console.log('Everything OK!');
     }
  );
}

And that's it, you have 3 functions that should be executed one after the other and no callback hell is needed.就是这样,你有 3 个函数应该一个接一个执行,不需要回调地狱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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