在函数中调用函数时异步Javascript上下文中的最佳实践?
我试图调用两个函数,并将第一个函数的输出作为参数传递给第二个函数 职能1:在函数中调用函数时异步Javascript上下文中的最佳实践?,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,我试图调用两个函数,并将第一个函数的输出作为参数传递给第二个函数 职能1: module.exports.getAllStatisticsByUserId = function(id, callback){ User.findById(id, (err, user) =>{ if(err) throw err; if(user) callback(null, user.statistics); }); }
module.exports.getAllStatisticsByUserId = function(id, callback){
User.findById(id, (err, user) =>{
if(err)
throw err;
if(user)
callback(null, user.statistics);
});
}
职能2:
module.exports.getGameByStatisticsId = function(id, callback){
Statistics.findById(id, (err, statistics) =>{
if(err)
throw err;
if(statistics)
callback(null, statistics.game);
});
};
我试图通过将第一个方法的输出作为参数传递来执行第二个方法,但是javascript的异步特性把它搞砸了。我曾试图履行承诺,但毫无结果
有人能推荐一些好的javascript实践来处理在相互需要时异步调用函数吗?任何帮助都将不胜感激。看起来您应该能够写:
getAllStatisticsByUserId("me", (err, stats) => {
getGameByStatisticsId(stats.id, (err, game) => {
console.log(game);
});
});
下面是这些函数返回承诺时的情况
getAllStatisticsByUserId("me")
.then(stats => getGameByStatisticsId(stats.id))
.then(game => console.log(game))
更好的是,如果您能够使用支持async/await
的Node版本,那么您可以编写
let stats = await getAllStatisticsByUserId("me");
let game = await getGameByStatisticsId(stats.id);
console.log(game);
这意味着略微重写原始函数(除非User.findById
和Statistics.findById
已经返回)
看起来你应该能够写:
getAllStatisticsByUserId("me", (err, stats) => {
getGameByStatisticsId(stats.id, (err, game) => {
console.log(game);
});
});
下面是这些函数返回承诺时的情况
getAllStatisticsByUserId("me")
.then(stats => getGameByStatisticsId(stats.id))
.then(game => console.log(game))
更好的是,如果您能够使用支持async/await
的Node版本,那么您可以编写
let stats = await getAllStatisticsByUserId("me");
let game = await getGameByStatisticsId(stats.id);
console.log(game);
这意味着略微重写原始函数(除非User.findById
和Statistics.findById
已经返回)
修复后,可以按如下顺序调用它们:
module.exports.getAllStatisticsByUserId = function(id, callback){
User.findById(id, (err, user) =>{
if(err) callback(err);
if(user) callback(null, user.statistics);
});
};
module.exports.getGameByStatisticsId = function(id, callback){
Statistics.findById(id, (err, statistics) =>{
if(err) callback(err);
if(statistics) callback(null, statistics.game);
});
};
someService.getAllStatisticsByUserId(id).then(statistics =>
someService.getGameByStatisticsId(statistics.id)
).then(game => {
// handle game
}).catch(err => {
// handle error
});
然而,如前所述:
当回调
函数未传递时,将返回一个查询实例,该实例提供了一个特殊的查询生成器界面。
查询具有.then()
函数,因此可以用作承诺
因此,您可以像这样简单地重写调用:
module.exports.getAllStatisticsByUserId = function(id, callback){
User.findById(id, (err, user) =>{
if(err) callback(err);
if(user) callback(null, user.statistics);
});
};
module.exports.getGameByStatisticsId = function(id, callback){
Statistics.findById(id, (err, statistics) =>{
if(err) callback(err);
if(statistics) callback(null, statistics.game);
});
};
someService.getAllStatisticsByUserId(id).then(statistics =>
someService.getGameByStatisticsId(statistics.id)
).then(game => {
// handle game
}).catch(err => {
// handle error
});
或者将其转换为async/await
函数:
async function getGameByUserId(id) {
try {
const statistics = await someService.getAllStatisticsByUserId(id);
const game = await someService.getGameByStatisticsId(statistics.id);
// handle game
} catch (error) {
// handle error
}
}
请注意,async
函数总是返回一个Promise
,因此您必须等待它或用链接它。然后()
以确保查询完成并解析返回的值(如果有)。修复后,您可以按如下顺序调用它们:
module.exports.getAllStatisticsByUserId = function(id, callback){
User.findById(id, (err, user) =>{
if(err) callback(err);
if(user) callback(null, user.statistics);
});
};
module.exports.getGameByStatisticsId = function(id, callback){
Statistics.findById(id, (err, statistics) =>{
if(err) callback(err);
if(statistics) callback(null, statistics.game);
});
};
someService.getAllStatisticsByUserId(id).then(statistics =>
someService.getGameByStatisticsId(statistics.id)
).then(game => {
// handle game
}).catch(err => {
// handle error
});
然而,如前所述:
当回调
函数未传递时,将返回一个查询实例,该实例提供了一个特殊的查询生成器界面。
查询具有.then()
函数,因此可以用作承诺
因此,您可以像这样简单地重写调用:
module.exports.getAllStatisticsByUserId = function(id, callback){
User.findById(id, (err, user) =>{
if(err) callback(err);
if(user) callback(null, user.statistics);
});
};
module.exports.getGameByStatisticsId = function(id, callback){
Statistics.findById(id, (err, statistics) =>{
if(err) callback(err);
if(statistics) callback(null, statistics.game);
});
};
someService.getAllStatisticsByUserId(id).then(statistics =>
someService.getGameByStatisticsId(statistics.id)
).then(game => {
// handle game
}).catch(err => {
// handle error
});
或者将其转换为async/await
函数:
async function getGameByUserId(id) {
try {
const statistics = await someService.getAllStatisticsByUserId(id);
const game = await someService.getGameByStatisticsId(statistics.id);
// handle game
} catch (error) {
// handle error
}
}
请注意,async
函数总是返回一个Promise
,因此您必须等待它或用链接它。然后()。。。不幸的是,你自己也这么说了:我建议你使用承诺。本教程对我非常有帮助:而不是throw err代码>您需要回调(err)代码>谢谢你的文章和提示!第一个方法没有输出。它所做的只是启动一个请求。当检索到该请求时,它可以选择调用一个可以访问结果的回调函数。因此,您希望在结果上执行的代码最好在该回调中,或者从该回调中调用。最佳实践?使用承诺。不要在异步回调中使用throw
。是的。。。不幸的是,你自己也这么说了:我建议你使用承诺。本教程对我非常有帮助:而不是throw err代码>您需要回调(err)代码>谢谢你的文章和提示!第一个方法没有输出。它所做的只是启动一个请求。当检索到该请求时,它可以选择调用一个可以访问结果的回调函数。因此,您希望在结果上执行的代码最好在该回调中,或者从该回调中调用。最佳实践?使用承诺。在异步回调中不要使用throw
。根据(假设基于findById()
的使用),只要省略回调参数,函数就会返回实现的对象。然后()
,所以不需要包装它们。@PatrickRoberts我认为Dan包装它们是正确的,因为问题是关于回调风格的代码,而不是具体的Mongoose方法。@PatrickRoberts我们怎么知道findById
意味着Mongoose?可能是,可能是一个自定义模型类。@PatrickRoberts可能是,但当我们对它们进行假设时,它对任何试图学习的人都没有帮助。据我们所知,询问者自己编写了findById
方法。我当然知道。我只是想确保这里的答案尽可能笼统,以便人们了解如何在所有情况下解决问题。根据(假设基于findById()
)的使用,只要省略回调参数,函数就会返回实现的对象。然后()
,所以不需要包装它们。@PatrickRoberts我认为Dan包装它们是正确的,因为问题是关于回调风格的代码,而不是具体的Mongoose方法。@PatrickRoberts我们怎么知道findById
意味着Mongoose?可能是,可能是一个自定义模型类。@PatrickRoberts可能是,但当我们对它们进行假设时,它对任何试图学习的人都没有帮助。据我们所知,询问者自己编写了findById
方法。我当然知道。我只是想确保这里的答案尽可能笼统,这样人们就能学会如何在所有情况下解决问题。