Mongoose: 在 promise catch 处理程序中处理 mongoose.connect() 错误的方法

创建于 2016-05-10  ·  31评论  ·  资料来源: Automattic/mongoose

如何在 catch 处理程序中处理mongoose.connect()错误? 我想使用应用程序初始化链但不能这样做,因为mongoose.connect()不会返回被拒绝的承诺。 仅当我指定回调时,它才会返回拒绝的承诺,但这不是一个完美的解决方案。

例子:

mongoose.connect('mongodb://127.0.0.2/test') // if error it will throw async error
    .then(() => { // if all is ok we will be here
        return server.start();
    })
    .catch(err => { // we will not be here...
        console.error('App starting error:', err.stack);
        process.exit(1);
    });

解决方法:

mongoose.connect('mongodb://127.0.0.2/test', function() { /* dummy function */ })
    .then(() => {
        return server.start();
    })
    .catch(err => { // mongoose connection error will be handled here
        console.error('App starting error:', err.stack);
        process.exit(1);
    });

我认为mongoose.connect()会抛出异步错误而不是返回被拒绝的承诺,以免破坏向后兼容性。 如果猫鼬连接建立出现问题,用户期望应用程序将完成错误代码。 如果mongoose.connect()返回被拒绝的 Promise 应用程序将以 0 代码完成,并且不会向控制台输出任何内容。 所以最好有某种方式说mongoose.connect()来回报承诺。 也许像exec()

mongoose.connect('mongodb://127.0.0.2/test').exec()
    .then(() => { // if all is ok we will be here
        return server.start();
    })
    .catch(err => { // if error we will be here
        console.error('App starting error:', err.stack);
        process.exit(1);
    });
can't reproduce

最有用的评论

只是为了确认以后来的任何人,这按预期工作:

mongoose.connect('http://127.0.0.1:27017/test')
  .then(() => {
    server.start();
  })
  .catch((err) => {
    console.log('Error on start: ' + err.stack);
    process.exit(1);
  });

所有31条评论

mongoose.connect('mongodb://localhost/dbCollection', function(err, db) {
    if (err) {
        console.log('Unable to connect to the server. Please start the server. Error:', err);
    } else {
        console.log('Connected to Server successfully!');
    }
});

@nasr18你是什​​么意思? :smiley: 我不想使用回调)

@Jokero对不起老兄............误解了你的问题。 :)

使用 mongoose.connect 的回调来捕获连接期间的任何错误。
您可以在事件打开时启动服务器。

        mongoose.connection.once('open', function() {
            logger.info('MongoDB event open');
            logger.debug('MongoDB connected [%s]', url);

            mongoose.connection.on('connected', function() {
                logger.info('MongoDB event connected');
            });

            mongoose.connection.on('disconnected', function() {
                logger.warn('MongoDB event disconnected');
            });

            mongoose.connection.on('reconnected', function() {
                logger.info('MongoDB event reconnected');
            });

            mongoose.connection.on('error', function(err) {
                logger.error('MongoDB event error: ' + err);
            });

            // return resolve();
            return server.start();
        });

        return mongoose.connect(url, options, function(err) {
            if (err) {
                logger.error('MongoDB connection error: ' + err);
                // return reject(err);
                process.exit(1);
            }
        });

@mathieug我知道,我可以使用回调来处理错误,但问题是关于承诺:笑脸:

不要使用来自 mongoose.connect 的承诺,当连接第一次打开时启动你的服务器 (.once('open'))

为什么? 完全没有区别。 当连接打开时, mongoose.connect回调将被调用,返回的 Promise 将被履行并发出open事件。 所以你可以使用你想要的

是的,但正如你所说, mongoose.connect 需要回调以防出错。

这就是我创建这个问题的原因:笑脸:

我有同样的问题。

我希望能够使用mongoose.connect(...).catch(failCallback)但是当初始连接尝试发生错误时failCallback不会执行。 mongoose.connect返回的MongooseThenable伪承诺有问题。 此外,我已经配置了mongoose.Promise = require('bluebird')并且我真的希望这样的异步调用能够返回一个 _real_ 承诺,在我的情况下是一个 Bluebird 承诺。

但是,我的failCallback未执行的问题仅在最初发生,即:

// First kill mongod instance so that Mongoose cannot connect and start the app
mongoose.connect(uri, options).catch(failCallback); // failCallback does _not_ get called
// Then stop the app, start mongod instance so that Mongoose can connect, start the app
mongoose.connect(uri, options).then(successCallback); // successCallback gets called
// Then kill mongod instance so that Mongoose disconnects (while the app is running)
mongoose.connection.on('disconnected', function () {
  setTimeout(function () {
    mongoose.connect(uri, options).catch(reconnectFailCallback); // now reconnectFailCallback _does_ get called
  }, randomDelayOfAboutASecond);
});

但确实它是这样工作的(这是荒谬的):

// First kill mongod instance so that Mongoose cannot connect and start the app
var dummyNoopCallback = function () {};
mongoose.connect(uri, options, dummyNoopCallback).catch(failCallback); // failCallback _does_ get called

这是为什么?

回复:返回一个真正的承诺,这是向后兼容的方式。 不幸的是,人们出于某种原因(#3847、#3790 等)依赖于.connect()链接行为,所以我们暂时保持这种方式:) 添加了一个修复程序,以便.catch()可以捕获初始连接问题。

有用! 但是对于那些期望在发生连接错误并且没有回调和承诺处理程序时完成应用程序进程的人来说,这些更改会破坏一些东西吗?

例子:

const mongoose = require('mongoose');
mongoose.Promise = Promise;

mongoose.connect('mongodb://127.0.0.2/test'); // no callback and promise handlers

在这些变化之前

/home/dmitry/example/node_modules/mongodb/lib/server.js:242
        process.nextTick(function() { throw err; })
                                      ^
Error: connect ECONNREFUSED 127.0.0.2:27017
    at Object.exports._errnoException (util.js:870:11)
    at exports._exceptionWithHostPort (util.js:893:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1057:14)

通过这些更改,过程以 0 代码完成

感谢您的建议,将调查。

凉爽的! 谢谢:+1:

+1
希望能够在初始化链接中将 .connect() 的结果作为完整的 Promise 返回。

@CodeJjang

mongoose.connect('mongodb://127.0.0.2/test', function() { /* dummy function */ })
    .then(() => {
        return server.start();
    })
    .catch(err => { // mongoose connection error will be handled here
        console.error('App starting error:', err.stack);
        process.exit(1);
    });

这对我不起作用:(
它显示
(node:22564) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: failed to connect to server [127.0.0.1:27017] on first connect

嗯,尝试摆脱mongoose.connect()中的回调

我刚得到:

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1):
MongoError: failed to connect to server [localhost:17551] on first connect

没有在 mongoose 4.7.6(现在最新)上使用承诺,有什么方法可以避免该警告?
我将它与 ExpressJS 一起使用,如果我使用 catch,它会破坏我的逻辑并且表现得很奇怪,因为express-session也在创建一个 MongoStore ......只是很乱。

请提供代码示例

我和@matheo有同样的问题。 刚打开这张票:

https://github.com/christkv/mongodb-core/issues/163

只是为了确认以后来的任何人,这按预期工作:

mongoose.connect('http://127.0.0.1:27017/test')
  .then(() => {
    server.start();
  })
  .catch((err) => {
    console.log('Error on start: ' + err.stack);
    process.exit(1);
  });

只是为了确认以后来的任何人,这按预期工作:

mongoose.connect('http://127.0.0.1:27017/test')
  .then(() => {
    server.start();
  })
  .catch((err) => {
    console.log('Error on start: ' + err.stack);
    process.exit(1);
  });

我也在使用这种方法! 但是当我停止 mongodb 然后运行这段代码时,它不起作用。

// mongoose version 5.4.14
mongoose
  .connect(databaseUri, {
    promiseLibrary: bluebird,
    useNewUrlParser: true,
    useFindAndModify: false,
    useCreateIndex: true,
    // Automatically try to reconnect when it loses connection to MongoDB
    autoReconnect: true,
    // Never stop trying to reconnect
    reconnectTries: Number.MAX_VALUE,
    // Reconnect every 500ms
    reconnectInterval: 500,
    // Maintain up to 10 socket connections. If not connected,
    // return errors immediately rather than waiting for reconnect
    poolSize: 10,
    // Give up initial connection after 10 seconds
    connectTimeoutMS: 10000,
  })
  .catch((err) => {
    console.log(err);
    process.exit(1);
  });

@nvtuan305 “不工作”是什么意思? 有一些错误信息吗?

@vkarpov15我的意思是不会打印错误

程序:

  • 第 1 步:我停止了 mongodb 服务
  • 第 2 步:连接 mongodb。 在这一步,控制台不会打印错误,不会到达catch块。
    // Never reach to here
    console.log(err);
    process.exit(1);

@nvtuan305如果初始连接超时, connectTimeoutMS之后报错。 你不是这样吗? 如果是这样,什么版本的 MongoDB 和猫鼬?

@vkarpov15

connectTimeoutMS之后mongoose会报错

在我的情况下,猫鼬在connectTimeoutMS catch块的

> mongod --version
db version v3.6.5
git version: a20ecd3e3a174162052ff99913bc2ca9a839d618
OpenSSL version: OpenSSL 1.0.2p  14 Aug 2018
allocator: system
modules: none
build environment:
    distarch: x86_64
    target_arch: x86_64

@nvtuan305只是为了确认一下,您是连接到独立的 mongodb 实例还是副本集?

@vkarpov15我正在使用独立实例。

@nvtuan305什么操作系统? 另外,为什么您认为 Mongoose 无法连接到独立设备 - mongod实例已关闭,是否没有网络连接,还是其他原因?

下面的脚本按预期工作:

const assert = require('assert');
const mongoose = require('mongoose');
mongoose.set('debug', true);

run().then(() => console.log('done')).catch(error => console.error(error.stack));

async function run() {
  console.log(mongoose.version);

  const start = Date.now();
  const opts = { useNewUrlParser: true, connectTimeoutMS: 1000 };
  await mongoose.connect('mongodb://doesntexist.com:27017/test', opts).
    catch(error => { console.log(`Caught "${error.message}" after ${Date.now() - start}`); });
}

输出

$ node gh-4135.js 
5.4.14
Caught "failed to connect to server [doesntexist.com:27017] on first connect [MongoNetworkError: connection 0 to doesntexist.com:27017 timed out]" after 1024
done
$ ^C

嘿,这似乎很基本,但请仔细检查这些说明

  • 在 Mongo 集群上设置你的 IP 地址,你甚至可以从任何地方设置访问
  • 一定要处理错误,例如使用 catch

我解决它这样做

此页面是否有帮助?
0 / 5 - 0 等级