在函数中调用函数时异步Javascript的上下文中的最佳实践?

时间:2018-02-27 17:00:14

标签: 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);

    });
}

功能2:

module.exports.getGameByStatisticsId = function(id, callback){

    Statistics.findById(id, (err, statistics) =>{
        if(err)
        throw err;
        if(statistics)
        callback(null, statistics.game);
    });
};

我试图通过将第一个方法的输出作为参数传递来执行第二个方法,但是javascript的异步性质正在弄乱它。我试过实施承诺无济于事。

任何人都可以建议一些好的javascript实践来处理在需要时异步调用函数吗?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

修复the issue I mentioned above后,您可以按顺序调用它们:

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, (err, statistics) => {
  if (err || !statistics) {
    // handle error
    return;
  }

  someService.getGameByStatisticsId(statistics.id, (err, game) => {
    if (err || !game) {
      // handle error
      return;
    }

    // handle game
  });
});

但是,如上所述in Mongoose documentation

  

如果未传递callback函数,则返回Query实例,该实例提供特殊的查询构建器界面。   Query具有.then()函数,因此可以用作承诺。

所以你可以简单地重写这样的调用:

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,因此您必须await或将其与.then()链接以确保查询完成并解决返回的问题价值,如果有的话。

答案 1 :(得分:1)

看起来你应该能写:

getAllStatisticsByUserId("me", (err, stats) => {
  getGameByStatisticsId(stats.id, (err, game) => {
    console.log(game);
  });
});

以下是这些函数返回promises时的样子。

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.findByIdStatistics.findById已经返回promises)。

module.exports.getAllStatisticsByUserId = function(id, callback){
    return new Promise((resolve, reject) => {
        User.findById(id, (err, user) =>{
            if(err) return reject(err);
            return resolve(user.statistics);
        });
    });
}