Как обработать ошибку mongoose.connect()
в обработчике catch? Я хочу использовать цепочку инициализации приложения, но не могу этого сделать, потому что 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()
вернет отклоненное обещание, приложение будет завершено с кодом 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);
});
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, чтобы поймать любую ошибку во время соединения.
Вы можете запустить свой сервер в событии open.
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 Я знаю, я могу использовать обратный вызов для обработки ошибок, но проблема в обещаниях :smiley:
Не используйте обещание от mongoose.connect, запустите свой сервер, когда соединение открыто в первый раз (.once('open'))
Почему? Никакой разницы. Когда соединение открыто, будет вызван обратный вызов mongoose.connect
, а также будет выполнено возвращенное обещание и будет сгенерировано событие open
. Таким образом, вы можете использовать то, что хотите
Да, но, как вы сказали, mongoose.connect нуждается в обратном вызове в случае ошибки.
Поэтому я и создал эту тему :smiley:
У меня такая же проблема.
Я хотел бы иметь возможность использовать mongoose.connect(...).catch(failCallback)
но когда возникает ошибка при первоначальной попытке подключения, failCallback
не выполняется. Там что - то не так с MongooseThenable
псевдо-обещание , что mongoose.connect
возвратов. Более того, я настроил mongoose.Promise = require('bluebird')
и действительно ожидаю, что такие асинхронные вызовы будут возвращать _real_ promise, в моем случае 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
Это почему?
Re: возврат реального обещания, это так для обратной совместимости. К сожалению, люди по какой-то причине полагаются на цепное поведение .connect()
(#3847, #3790 и т. д.), поэтому мы пока оставляем его таким :) Добавлено исправление, позволяющее .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() в виде полноценного промиса в цепочке инициализации.
@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
не используя обещания на мангусте 4.7.6 (последняя прямо сейчас), есть ли способ избежать этого предупреждения?
Я использую его с ExpressJS, и если я использую catch, он портит мою логику и ведет себя странно, поскольку express-session
тоже создает MongoStore... просто беспорядочно.
Пример кода пожалуйста
У меня та же проблема, что и у @mateo. Только что открыл этот тикет:
Просто чтобы подтвердить для тех, кто придет позже, это работает, как и ожидалось:
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 Я имею в виду, что ошибка не будет напечатана
Процедура:
catch
не будет достигнут. // Never reach to here
console.log(err);
process.exit(1);
@ nvtuan305 nvtuan305, если время ожидания исходного соединения истекло, мангуст сообщит об ошибке после connectTimeoutMS
. Разве это не так для вас? Если да, то какая версия MongoDB и мангуста?
@vkarpov15
мангуст сообщит об ошибке после
connectTimeoutMS
В моем случае мангуст не сообщает об ошибке после connectTimeoutMS
в блоке catch
. Я использую MongoDB 3.6.5 и мангуст 5.4.14.
> 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
Эй, это кажется простым, но, пожалуйста, перепроверьте эти инструкции
Я решаю это, делая это
Самый полезный комментарий
Просто чтобы подтвердить для тех, кто придет позже, это работает, как и ожидалось: