¿Cómo manejar el error mongoose.connect()
en el controlador de captura? Quiero usar la cadena de inicialización de la aplicación, pero no puedo hacerlo porque mongoose.connect()
no devuelve la promesa rechazada. Devuelve la promesa rechazada solo si especifico devolución de llamada, pero no es una solución perfecta.
Ejemplo:
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);
});
Solución alterna:
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);
});
Creo que mongoose.connect()
arroja un error asíncrono en lugar de devolver una promesa rechazada para no romper la compatibilidad con versiones anteriores. Los usuarios esperan que la aplicación finalice con un código de error si algo salió mal con el establecimiento de la conexión de mangosta. Si mongoose.connect()
devuelve la aplicación de promesa rechazada se terminará con el código 0 y no se enviará nada a la consola. Así que será bueno tener alguna forma de decir mongoose.connect()
para devolver la promesa. Tal vez algo como 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 ¿Qué quisiste decir? :smiley: no quiero usar devolución de llamada)
@Jokero, lo siento, amigo
Utilice la devolución de llamada de mongoose.connect para detectar cualquier error durante la conexión.
Puede iniciar su servidor en el evento abierto.
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 Lo sé, puedo usar la devolución de llamada para el manejo de errores, pero el problema se trata de promesas :smiley:
No use la promesa de mongoose.connect, inicie su servidor cuando la conexión esté abierta por primera vez (.once('open'))
¿Por qué? No hay diferencia en absoluto. Cuando se abre la conexión, se llamará a la devolución mongoose.connect
llamada open
. Para que puedas usar lo que quieras
Sí, pero como dijiste, mongoose.connect necesita una devolución de llamada en caso de error.
Por eso creé este problema :smiley:
Tengo el mismo problema.
Me gustaría poder usar mongoose.connect(...).catch(failCallback)
pero cuando ocurre un error en el intento de conexión inicial, failCallback
no se ejecuta. Hay algo mal con el MongooseThenable
seudo-promesa de que mongoose.connect
devoluciones. Además, he configurado mongoose.Promise = require('bluebird')
y realmente espero que tales llamadas asincrónicas devuelvan una promesa _real_, una Bluebird en mi caso.
Sin embargo, el problema con mi failCallback
no se ejecuta ocurre solo inicialmente, es decir:
// 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);
});
Pero de hecho funciona así (lo cual no tiene sentido):
// 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
¿Porqué es eso?
Re: devolver una promesa real, es así por compatibilidad con versiones anteriores. Desafortunadamente, las personas confían en el comportamiento de encadenamiento de .connect()
por alguna razón (#3847, #3790, etc.), por lo que lo mantendremos así por ahora :) Se agregó una solución para que .catch()
pueda captar la conexión inicial asuntos.
¡Funciona! Pero, ¿estos cambios romperán algo para aquellos que esperan que el proceso de solicitud finalice cuando ocurra un error de conexión y no haya controladores de devolución de llamada y promesa?
Ejemplo:
const mongoose = require('mongoose');
mongoose.Promise = Promise;
mongoose.connect('mongodb://127.0.0.2/test'); // no callback and promise handlers
Antes de estos cambios
/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)
Con estos cambios el proceso finaliza con código 0
Gracias por la sugerencia, investigaré.
¡Frio! Gracias :+1:
+1
Me encantaría poder devolver el resultado de .connect() como una Promesa completa en el encadenamiento de inicialización.
@CodeJjang, ¿esto no funciona ya? Esta funcionalidad ya ha sido lanzada
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);
});
esto no me funciona :(
Muestra
(node:22564) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: failed to connect to server [127.0.0.1:27017] on first connect
Hmm, intenta deshacerte de la devolución de llamada en mongoose.connect()
Acabo de tener:
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1):
MongoError: failed to connect to server [localhost:17551] on first connect
no usar promesas en mongoose 4.7.6 (más reciente en este momento), ¿alguna forma de evitar esa Advertencia?
Lo estoy usando con ExpressJS y si uso catch, arruina mi lógica y se comporta de manera extraña ya que express-session
está creando un MongoStore... simplemente desordenado.
ejemplo de código por favor
Tengo el mismo problema que @matheo. Acabo de abrir este ticket:
Solo para confirmar para cualquiera que venga más tarde, esto funciona como se esperaba:
mongoose.connect('http://127.0.0.1:27017/test')
.then(() => {
server.start();
})
.catch((err) => {
console.log('Error on start: ' + err.stack);
process.exit(1);
});
Solo para confirmar para cualquiera que venga más tarde, esto funciona como se esperaba:
mongoose.connect('http://127.0.0.1:27017/test') .then(() => { server.start(); }) .catch((err) => { console.log('Error on start: ' + err.stack); process.exit(1); });
¡También estoy usando este enfoque! Pero cuando detengo mongodb y luego ejecuto este código, no funciona.
// 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, ¿qué quiere decir con 'no funciona'? ¿Hay algunos mensajes de error?
@ vkarpov15 Quiero decir que no se imprimirá ningún error
Procedimiento:
catch
. // Never reach to here
console.log(err);
process.exit(1);
@ nvtuan305 si se connectTimeoutMS
. ¿No es ese tu caso? Si es así, ¿qué versión de MongoDB y mongoose?
@vkarpov15
mangosta informará un error después de
connectTimeoutMS
En mi caso, la mangosta no informa el error después de connectTimeoutMS
en el bloque catch
. Estoy usando Mongodb 3.6.5 y mongoose 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 solo para confirmar, ¿se está conectando a una instancia mongodb independiente o un conjunto de réplicas?
@ vkarpov15 Estoy usando una instancia independiente.
@ nvtuan305 ¿qué sistema operativo? Además, ¿por qué espera que Mongoose no se conecte a la instancia independiente? ¿Está caída la instancia de mongod
, no hay conexión de red, algo más?
El siguiente script funciona como se esperaba:
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}`); });
}
Producción
$ 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
Oye, parece básico, pero por favor revisa estas instrucciones.
lo soluciono haciendo eso
Comentario más útil
Solo para confirmar para cualquiera que venga más tarde, esto funciona como se esperaba: