如何确保在从 Mongoose 中的函数返回之前执行异步调用?
Posted
技术标签:
【中文标题】如何确保在从 Mongoose 中的函数返回之前执行异步调用?【英文标题】:How to ensure an asynchronous call is executed before returning from a function in Mongoose? 【发布时间】:2015-10-22 03:03:16 【问题描述】:我是 mongoose 的新手,为了防止 ASYNC OF HELL,我偶然发现了一个名为 async 的 npm 包。我使用了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
这里我使用了一个异步序列函数来防止 HELL 的 ASYNC。我在异步系列调用中调用findUser
函数,该函数使用userId
从我的User
模型中查找用户详细信息,然后我调用findSchool
函数inside @987654330 @ 函数在School
模型中查找给定SchoolId
的学校详细信息。一旦函数返回调用,我将尝试使用 Student
模型上的 findStudents
函数根据特定的 schoolName
查找学生。
对不同的schoolId
重复该过程。当我调用 findSchool
函数时,我的问题就出现了。由于它在 school
模型上具有异步调用 (findOne
),因此即使在模型的 findOne
完成之前,我也能够返回 schoolName
的值。
有没有办法确保给定函数findSchool
在school.findOne()
成功完成之前不会返回schoolName
的值?只是为了更清楚地说明我不想在findSchool
函数的findOne
内部 我的返回语句。
【问题讨论】:
使用异步瀑布 - github.com/caolan/async#waterfall 【参考方案1】:您仍应使用async
,但您需要async.waterfall
。以下是您需要考虑的事项:
调用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!');
);
那么你需要你的函数对async
友好,这意味着你应该使用回调并将数据从一个函数传递给另一个函数。像这样的:
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
那么你应该在你的 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!');
);
就是这样,你有 3 个函数应该一个接一个地执行,不需要回调地狱。
【讨论】:
嗨 Gesser 如果我的 findUser 多次调用我的 findSchool 函数怎么办。那里会有异步瀑布吗?假设我有多个 SchoolId,我在我的 findUser 函数中放置了一个 for 循环,在这种情况下异步瀑布有助于吗? @shubhamagiwal 很高兴它对您有所帮助。你应该阅读async
doc,你可以用它做任何与工作流相关的事情。【参考方案2】:
我认为 Async.each 或 async.waterfall 应该可以解决问题。
这里的主要问题是您在异步函数中使用了 return 语句,它将在异步函数实际完成之前返回,因此它们不会传递您需要的内容。
您必须为此使用异步函数和回调。你仍然可以在你的代码中按照你想要的方式分离你的函数,但是你必须添加回调函数而不是返回。
【讨论】:
以上是关于如何确保在从 Mongoose 中的函数返回之前执行异步调用?的主要内容,如果未能解决你的问题,请参考以下文章
如何在从 Meteor.method 返回之前等待子流程结果
在从 HttpClient 请求获得的对象转换新类型之前,如何使用 rxjs 映射来改变对象中的数据?