Javascript 如何使用不同模块中的嵌套承诺正确处理错误
我是Node JS的新手,在使用promises时,我很难正确处理错误。 以下是我目前拥有的: 我有一个模块调用db.js,其中包含一个init函数,用于设置和启动db连接:Javascript 如何使用不同模块中的嵌套承诺正确处理错误,javascript,node.js,express,error-handling,promise,Javascript,Node.js,Express,Error Handling,Promise,我是Node JS的新手,在使用promises时,我很难正确处理错误。 以下是我目前拥有的: 我有一个模块调用db.js,其中包含一个init函数,用于设置和启动db连接: function initDb(){ return new Promise((resolve, reject) => { if(database){ console.warn("Trying to init DB again !") }else{ client.conn
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)
})}
此函数将返回一个承诺,并将其调用到index.js中:
initDb()
.then(() => {
app.listen(8081, function () {
console.log('App is running on port 8081')
})
})
.catch((error) => {
console.log(error)
})
正如你所看到的,我有两个陷阱。一个在db模块中,另一个在index.js中
在两个地方发现错误是很奇怪的。。。在这种情况下,处理错误的好模式是什么 如果您没有在db.js模块的initDb函数中写入catch,您可以在调用函数中捕获该错误,因此如果您没有在db.js模块中写入.catch((err)=>{reject(err)}),则错误将转到index.js中的调用函数,您可以直接在那里处理它 在两个位置捕获错误并不奇怪,事实上,在即将发布的node版本中,这将是一种推荐的做法,即编写捕获(err)来处理所有承诺中的错误。您将希望避免错误。另外,不要将
数据库本身存储在变量中,而是存储它的承诺
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;
}
为什么你要设定一个新的承诺,里面有一个承诺?如果我正确阅读了你的代码,client.connect也会返回一个承诺谢谢,非常有趣的帖子!我只有一个问题。我现在使用的是initDb()连接db对象并将其存储在变量中,还有另一个函数:getDb(),用于检索db对象,因此我可以在其他模块中导入该对象并非常轻松地使用它。但是您提到不要存储数据库对象。但是如果我存储了承诺,那么我就失去了轻松调用db的能力。代码将类似于:getDb().then((db)=>{return db.collection('foo').find()}),而不仅仅是getDb().collection.find()。我是否遗漏了什么?您如何确保数据库调用代码仅在连接初始化后运行?也许可以将db
作为需要它的函数的显式参数,而不是使用getDb
函数,您可以在任何地方导入它。(也适用于控制反转)