如何在不同模块中使用嵌套承诺正确处理错误

时间:2019-09-06 10:22:48

标签: javascript node.js express error-handling promise

我是Node JS的新手,并且在使用Promise时要努力正确地处理错误。 这是我目前拥有的:

我有一个带有初始化功能的模块调用db.js,该功能用于设置和启动db连接:

function initDb(){
return new Promise((resolve, reject) => {
    if(database){
        console.warn("Trying to init DB again !")
    }else{
        client.connect(config.db.url, {useNewUrlParser: true, useUnifiedTopology: true})
        .then((client) => {
            console.log("DB initialized - connected to database: " + config.db.name)
            database = client.db(config.db.name)
        })
        .catch((err) => {
            reject(err)
        })
    }
    resolve(database)
})}

此函数将返回一个promise,它将被调用到index.js中:

initDb()
.then(() => {
    app.listen(8081, function () {
        console.log('App is running on port 8081')
    })
})
.catch((error) => {
    console.log(error)
})

您可以看到我有两个陷阱。一个在db模块中,另一个在index.js中

在两个地方捕获错误似乎很奇怪……在这种情况下,用来处理错误的好的模式是什么?

2 个答案:

答案 0 :(得分:2)

您要避免使用Promise constructor antipattern。另外,请勿将database本身存储在变量中,而应将其承诺存储在其中。

let databasePromise;
function initDb() {
    if (databasePromise) {
        console.debug("DB already initialised");
        return databasePromise;
    }
    databasePromise = client.connect(config.db.url, {useNewUrlParser: true, useUnifiedTopology: true})
    .then((client) => {
        console.log("DB initialized - connected to database: " + config.db.name)
        return client.db(config.db.name)
    });
    return databasePromise;
}

答案 1 :(得分:-1)

如果您没有在db.js模块的initDb函数中编写catch,则可以在调用函数中捕获该错误,因此如果您不编写.catch((err)=> { err)})在db.js模块中,错误将转到index.js中的调用函数,您可以在那里直接处理它。

在两个地方都捕获错误并不奇怪,实际上,在以后的节点版本中,推荐编写catch(err)来处理所有承诺的错误的做法。