javascript-Node使用Promise.all和.catch()语句为Mongoose请求抛出UnhandledPromiseRejectionWarning

前端之家收集整理的这篇文章主要介绍了javascript-Node使用Promise.all和.catch()语句为Mongoose请求抛出UnhandledPromiseRejectionWarning 前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我是Node / Mongoose的新手,正在尝试正确处理脚本中的错误以将玩家添加到联赛中.在下面的代码中,.catch()语句正确捕获了显式引发的和与Promise不相关的错误,但是被拒绝的Promise却没有.

例如,尝试传递无效的userID会导致找不到用户.

但是,如果我通过断开数据库测试Promise拒绝,则会得到以下信息:

(node:6252) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoNetworkError: Failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]

我是否以某种方式错误地使用了Promise.all()和.catch()?

为了清楚起见,我试图弄清楚为什么不处理错误,而不是为什么引发错误.

我的剧本:

const 
mongoose = require('mongoose'),User = require('./models/users'),League = require('./models/leagues'),dbUrl = process.env.DBURL || 'mongodb://localhost/predictor';

mongoose.connect(dbUrl,{ useNewUrlParser: true });

const addUserToLeague = (userId,leagueId) => {
    let foundUser = User.findById(userId);
    let foundLeague = League.findById(leagueId);

    return Promise.all([foundUser,foundLeague])
    .then(arr => {
        if(!arr[0]){
            throw 'User not found';
        }else if(!arr[1]){
            throw 'League not found';
        }
        return arr;
    })
    .then(arr => {
        arr[0].leagueMemberships.push(arr[1]);
        arr[1].users.push(arr[0]);
        return arr;
    })
    .then(updatedArr => {
        updatedArr[0].save();
        updatedArr[1].save();
        return updatedArr;
    })
    .then(updatedArr => { console.log(`User ${updatedArr[0]._id} added to league ${updatedArr[1]._id}`) })
    .catch(err => { console.log('Error:',err) });
};

addUserToLeague(process.argv[2],process.argv[3]); // Needs 2 args: User ID and League ID
最佳答案
正如Bergi指出的那样,该错误似乎是由于connect造成的,您根本没有处理returns a promise-包括不等待它完成.因此,至少需要处理以下事项:

const connectionPromise = mongoose.connect(dbUrl,{ useNewUrlParser: true })
    .catch(error => {
        // Handle connection error
    });

然后在addUserToLeague中:

const addUserToLeague = (userId,leagueId) => {
    return connectionPromise.then(connection => {
        // ...logic here
    });
};

…但是,我质疑在这样加载模块时是否应该连接,而不是将连接传递给addUserToLeague.

除此之外,Promise.all的实际使用还可以,但是:

>有人希望,如果找不到该项目,则findById不会用虚假的值来解决诺言,因此整个处理程序似乎是不必要的.
>可能保存会带来希望.您不会处理拒绝,也不会等待解决.
>我会使用解构来避免arr [0]和arr [1],因为很容易忘记顺序.
>没有理由将带有push调用的then处理程序与进行保存的then处理程序分开.
> addUserToLeague应该返回承诺链的结果,以便调用它的代码A)知道何时完成,B)知道何时失败.
>错误不应在addUserToLeague中处理;而是在调用方中处理它们.
>还存在数据为denormalized的问题:您正在将成员资格信息存储在用户对象和联盟对象中.也许在文档数据库中这是相对正常的(我不知道).在RDBMS中,您会将信息存储在一个地方.从addUserToLeague中的代码中可以清楚地看出原因:如果保存用户成功但保存联盟失败怎么办?然后,用户对象说它是联赛的成员,而联赛对象没有说它是联赛的成员.还有一个问题是,由于它存储在两个地方,即使没有问题,在很短的时间内,其中一个(用户或联盟)将被保存,而另一个则不会被保存.两者都是完整性问题.如果您可以将其标准化为将此信息存储在一个地方,那将是很好的.如果不能,则需要更新代码,以便保存其中一个,等待代码成功,再保存另一个,如果失败,则尝试撤消对第一个所做的更改.

这样的事情(我不试图在这里解决规范化问题,这是一个大图景):

const 
mongoose = require('mongoose'),dbUrl = process.env.DBURL || 'mongodb://localhost/predictor';

const addUserToLeague = (connection,userId,leagueId) => {
    return Promise.all([
        User.findById(userId),League.findById(leagueId)
    ])
    .then(([user,league]) => {
        user.leagueMemberships.push(league);
        league.users.push(user);
        return Promise.all([user.save(),league.save()]);
    })
    .then((([user,league]) => {
        console.log(`User ${user._id} added to league ${league._id}`);
    });
};

mongoose.connect(dbUrl,{ useNewUrlParser: true })
.then(connection => addUserToLeague(connection,process.argv[2],process.argv[3]) // Needs 2 args: User ID and League ID
.catch(error => {
    // Handle/report error
});

如果您正在使用Node的最新版本,则可以使用async函数

const 
mongoose = require('mongoose'),dbUrl = process.env.DBURL || 'mongodb://localhost/predictor';

const addUserToLeague = async (connection,leagueId) => {
    let [user,league] = await Promise.all([
        User.findById(userId),League.findById(leagueId)
    ]);
    user.leagueMemberships.push(league);
    league.users.push(user);
    [user,league] = await Promise.all([user.save(),league.save()]);
    console.log(`User ${user._id} added to league ${league._id}`);
};

mongoose.connect(dbUrl,process.argv[3]) // Needs 2 args: User ID and League ID
.catch(error => {
    // Handle/report error
});

猜你在找的JavaScript相关文章