Catch 在连接到 Mongo 时失败 [英] Catch fails on connection to Mongo
问题描述
这个问题的答案:How当 mongo 连接失败时让节点退出 包含连接的异步/等待代码
the answer to this question: How to get node to exit when mongo connect fails contains async/wait code for a connection
但是,我的代码(在节点 v11.5.0 和 mongodb v3.1.13 上运行)未能捕获:
however, my code (running on node v11.5.0 and mongodb v3.1.13) is failing to catch:
(async function() {
let db;
try {
db = await MongoClient.connect(uri, { useNewUrlParser: true });
console.log("RETURN", db);
} catch (err) {
console.log('EXITING');
process.exit(1);
}
}());
为了证明我故意给出一个没有凭据的 uri:
to prove the point I intentionally give a uri without credentials:
mongodb://undefined@cluster0-shard-00-00-z4j9e.azure.mongodb.net:27017,cluster0-shard-00-01-z4j9e.azure.mongodb.net:27017,cluster0-shard-00-02-z4j9e.azure.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin&retryWrites=true
mongodb://undefined@cluster0-shard-00-00-z4j9e.azure.mongodb.net:27017,cluster0-shard-00-01-z4j9e.azure.mongodb.net:27017,cluster0-shard-00-02-z4j9e.azure.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin&retryWrites=true
我得到的是这样的输出:
and what I get is output like this:
/Users/ekkis/dev/mongo/node_modules/mongodb/lib/topologies/replset.js:346抛出错误;^
/Users/ekkis/dev/mongo/node_modules/mongodb/lib/topologies/replset.js:346 throw err; ^
MongoError:密码必须是字符串在 passwordDigest (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/auth/scram.js:63:43)在 ScramSHA1.ScramSHA.auth (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/auth/scram.js:175:25)在身份验证 (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/connection/pool.js:232:17)在 authenticationLiveConnections (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/connection/pool.js:819:7)在/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/connection/pool.js:864:5在 waitForLogout (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/connection/pool.js:855:34)在 Pool.auth (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/connection/pool.js:862:3)在 Server.auth (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/topologies/server.js:931:20)在 auth (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/topologies/replset.js:1474:19)在 ReplSet.auth (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/topologies/replset.js:1492:5)
MongoError: password must be a string at passwordDigest (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/auth/scram.js:63:43) at ScramSHA1.ScramSHA.auth (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/auth/scram.js:175:25) at authenticate (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/connection/pool.js:232:17) at authenticateLiveConnections (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/connection/pool.js:819:7) at /Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/connection/pool.js:864:5 at waitForLogout (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/connection/pool.js:855:34) at Pool.auth (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/connection/pool.js:862:3) at Server.auth (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/topologies/server.js:931:20) at auth (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/topologies/replset.js:1474:19) at ReplSet.auth (/Users/ekkis/dev/mongo/node_modules/mongodb-core/lib/topologies/replset.js:1492:5)
所以如果错误被捕获,控制台应该显示退出"这个词,但没有.另外,我认为抛出了一个异常,因为否则返回的值会被打印出来,而不是
so if the error had been caught, the console should have displayed the word 'EXITING', but does not. additionally, I contend an exception was thrown because otherwise the returned value would have been printed, which it was not
这怎么可能?我需要做什么才能让它工作?
how can this be? what do I need to do to get it to work?
* 附录 I *
事实上,promise 版本也表现出同样奇怪的行为,它没有捕获:
In fact, the promises version of this exhibits the same odd behaviour, it doesn't catch:
MongoClient
.connect(uri, { useNewUrlParser: true })
.then(dbc => {
console.log('SUCCESS');
})
.catch(err => {
console.log('EXITING');
process.exit(1);
});
是的,我测试了回调版本,它也有同样的问题.顺便说一句,为 uri 传递一个空字符串效果很好.没看懂
and yes, I tested the callback version, which also suffers the same malady. Incidentally, passing an empty string for the uri works well. I don't get it
* 附录二 *
事实上,问题似乎与传递的凭据有关,即如果我通过:
In fact, the problem seems to be particular to the credentials passed i.e. if I pass:
mongodb://x:y@cluster0-shard-[...]
mongodb://x:y@cluster0-shard-[...]
我按预期捕获了MongoError:身份验证失败".路过:
I catch a "MongoError: authentication fail" as expected. passing:
mongodb://@cluster0-shard-[...]
mongodb://@cluster0-shard-[...]
有趣的是返回一个连接但缺少:"的凭据以这种奇怪的方式失败,因此:
interestingly returns a connection but credentials missing a ":" fail in this odd way, so:
mongodb://ekkis@cluster0-shard-[...]
mongodb://ekkis@cluster0-shard-[...]
未能抓住
推荐答案
在我看来这是一个错误,但是 MongoClient 正在设置其连接.您将无法使用 try
&catch
处理 MongoClient 代码中异步抛出的错误.
Looks to me like it's a bug with however MongoClient is setting up its connections. You won't be able to use try
& catch
to handle asynchronously thrown errors within MongoClient code.
const {MongoClient} = require("mongodb");
process.on("uncaughtException", (err) => {
console.log("process err", err);
process.exit(1)
})
async function run () {
let db;
try {
// connection url will throw because password isn't provided
db = await MongoClient.connect("mongodb://myUsername:@localhost", { useNewUrlParser: true });
} catch (err) {
console.log('Exiting from thrown error', err);
process.exit(1);
}
}
run();
这是发生了什么的简化示例 - 错误最终会未捕获"并被 uncaughtException 处理程序捕获
Here's a simplified example of what's happening -- the error will end up "uncaught" and caught by the uncaughtException handler
process.on("uncaughtException", (err) => console.log("uncaught", err));
try {
setTimeout(() => {
throw new Error("asynchronously thrown error");
})
} catch (err) {
console.log("Error will not be caught here")
}
这篇关于Catch 在连接到 Mongo 时失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!