首页 > 解决方案 > Mongoose Promise 未填充到脚本中

问题描述

我有一个 api 服务器和一些脚本作业。他们使用相同的功能来使用 mongoose 拉出名册并填充名册中的球员。在api服务器上,这个函数是正常调用的。使用脚本,它不会。

API 示例

function getRoster(id) {
    var deferred = Q.defer();

    Roster.find({_id:id}, 'playerRoster userId tournamentId').populate('playerRoster').exec(
        function(err, roster) {
            if (err) {
                deferred.resolve(err);
            }
            deferred.resolve(roster[0]);
        });
    return deferred.promise;
}
api.post('/get_roster', function(req, res) {
        // get tournament
        var id = req.body._id;
        var playerId = req.body.playerId;
        getRoster(id).then(function(data) {
            var roster=data;
            res.json(roster);
        });
    });

脚本

module.exports = function(config) {
    this.getRoster=function(id) {
            //return Roster.find({_id:id}, 'playerRoster userId tournamentId').exec( - THIS RETURNS
            return Roster.find({_id:id}, 'playerRoster userId tournamentId').populate('playerRoster').exec(
                function(err, roster) {
                    if (err) {
                        return err;
                    }
                    console.log('roster[0]',roster);
                    return roster[0];
                });
        }

   this.tallyPoints = function(tournamentPlayer,sportsPlayers) {
        var deferred = Q.defer();
        var totalPoints =0;
        console.log("tallyPoints 0 ",tournamentPlayer);
        var rosterId = tournamentPlayer.player.roster[0];
        console.log("tallyPoints 1 ",rosterId);
        this.getRoster(rosterId).then(function(roster2){
            console.log("tallyPoints 2 ",roster2);
            ...
            deferred.resolve(totalPoints);
        });
        return deferred.promise;
    }

    return this;

};

在脚本中,记录 roster[0] 或 tallyPoints 2 行都不会打印,但也没有错误。

为什么我添加填充时 Roster.find 不返回?我唯一能想象的是因为 playerRoster 集合有 2000 条记录搜索 ~10 并且它遇到了一些没有被捕获的超时。

任何清理它的建议也值得赞赏。谢谢

标签: node.jsmongoose

解决方案


Moongoose 长期支持 Promise。在需要 promise 的地方使用基于回调的 Mongoose API 是不合适的,并且Q.defer与现有的 promise 一起使用被称为 Deferred 反模式(类似地,new Promise会导致 promise 构造反模式)。

在其当前状态下getRoster,不会返回承诺,也不会正确处理错误。

function getRoster(id) {
    return Roster.find({_id:id}, 'playerRoster userId tournamentId').populate('playerRoster').exec()
    .then(roster => roster[0]);
}

api.post('/get_roster', function(req, res) {
    // get tournament
    var id = req.body._id;
    var playerId = req.body.playerId;
    getRoster(id)
    .then(function(data) {
        var roster=data;
        res.json(roster);
    })
    .catch(err => {
        // handle error
    });
});

考虑到 onlyroster[0]被使用,它可能应该改为Roster.findOne.

无论getRoster是在 Express 路线还是其他地方使用都没有关系,它应该可以工作。未知module.exports = function(config) {...}模块是如何使用的,但this如果它不用作类,可能会引用错误的上下文。如果不使用getRoster,它们不应驻留在此函数中。tallyPointsconfig


推荐阅读