Como lidar com o erro mongoose.connect()
no manipulador de captura? Eu quero usar a cadeia de inicialização do aplicativo, mas não posso fazer isso porque mongoose.connect()
não retorna a promessa rejeitada. Ele retorna a promessa rejeitada apenas se eu especificar o retorno de chamada, mas não é uma solução perfeita.
Exemplo:
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);
});
Gambiarra:
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);
});
Eu acho que mongoose.connect()
lança um erro assíncrono em vez de retornar a promessa rejeitada para não quebrar a compatibilidade com versões anteriores. Os usuários esperam que o aplicativo seja finalizado com o código de erro se algo der errado com o estabelecimento da conexão do mangusto. Se mongoose.connect()
retornar, o aplicativo de promessa rejeitado será finalizado com código 0 e nada será enviado para o console. Então será bom ter alguma forma de dizer mongoose.connect()
para devolver a promessa. Talvez 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 O que você quis dizer? :smiley: não quero usar callback)
@Jokero desculpe cara ......... não
Use o retorno de chamada de mongoose.connect para detectar qualquer erro durante a conexão.
Você pode iniciar seu servidor no evento aberto.
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 Eu sei, posso usar o retorno de chamada para tratamento de erros, mas o problema é sobre promessas :smiley:
Não use a promessa de mongoose.connect, inicie seu servidor quando a conexão for aberta pela primeira vez (.once('open'))
Por quê? Nenhuma diferença. Quando a conexão for aberta, o callback mongoose.connect
será chamado, assim como a promessa retornada será cumprida e o evento open
será emitido. Então você pode usar o que quiser
Sim, mas como você disse, mongoose.connect precisa de um retorno de chamada em caso de erro.
Por isso criei esta edição :smiley:
Eu tenho o mesmo problema.
Eu gostaria de poder usar mongoose.connect(...).catch(failCallback)
mas quando ocorre um erro na tentativa inicial de conexão failCallback
não executa. Há algo errado com a pseudo-promessa MongooseThenable
que mongoose.connect
retorna. Além disso, configurei mongoose.Promise = require('bluebird')
e realmente espero que essas chamadas assíncronas retornem uma promessa _real_, uma promessa Bluebird no meu caso.
O problema do meu failCallback
não executar, porém, acontece apenas inicialmente, ou seja:
// 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);
});
Mas de fato funciona assim (o que não faz 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
Por que é que?
Re: retornar uma promessa real, é assim para compatibilidade com versões anteriores. Infelizmente, as pessoas confiam no comportamento de encadeamento .connect()
por algum motivo (#3847, #3790, etc), então estamos mantendo assim por enquanto :) Adicionada uma correção para que .catch()
possa capturar a conexão inicial questões.
Funciona! Mas essas mudanças quebrarão algo para aqueles que esperam que o processo do aplicativo seja concluído quando ocorrer um erro de conexão e não houver manipuladores de retorno de chamada e promessa?
Exemplo:
const mongoose = require('mongoose');
mongoose.Promise = Promise;
mongoose.connect('mongodb://127.0.0.2/test'); // no callback and promise handlers
Antes dessas mudanças
/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)
Com essas alterações o processo é finalizado com 0 código
Obrigado pela sugestão, vou investigar.
Legal! Obrigado :+1:
+1
Adoraria poder retornar o resultado de .connect() como uma promessa completa no encadeamento de inicialização.
@CodeJjang isso já não funciona? Esta funcionalidade já foi lançada
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);
});
Isso não está funcionando para mim :(
Isso mostra
(node:22564) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: failed to connect to server [127.0.0.1:27017] on first connect
Hmm tente se livrar do callback em mongoose.connect()
Eu acabei de receber:
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1):
MongoError: failed to connect to server [localhost:17551] on first connect
não usando promessas no mangusto 4.7.6 (mais recente agora), alguma maneira de evitar esse aviso?
Estou usando com ExpressJS e se eu usar catch, ele estraga minha lógica e se comporta de forma estranha, pois express-session
está criando um MongoStore também... apenas confuso.
Exemplo de código por favor
Estou com o mesmo problema do @matheo. Acabei de abrir este ticket:
Apenas para confirmar para quem vem mais tarde, isso funciona como esperado:
mongoose.connect('http://127.0.0.1:27017/test')
.then(() => {
server.start();
})
.catch((err) => {
console.log('Error on start: ' + err.stack);
process.exit(1);
});
Apenas para confirmar para quem vem mais tarde, isso funciona como esperado:
mongoose.connect('http://127.0.0.1:27017/test') .then(() => { server.start(); }) .catch((err) => { console.log('Error on start: ' + err.stack); process.exit(1); });
Estou usando essa abordagem também! Mas quando eu paro o mongodb e executo este código, não está funcionando.
// 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 o que você quer dizer com 'não está funcionando'? Existem algumas mensagens de erro?
@vkarpov15 Quero dizer que nenhum erro será impresso
Procedimento:
catch
não será alcançado. // Never reach to here
console.log(err);
process.exit(1);
@nvtuan305 se a conexão inicial connectTimeoutMS
. Não é esse o seu caso? Em caso afirmativo, qual versão do MongoDB e do mangusto?
@vkarpov15
mangusto irá relatar um erro após
connectTimeoutMS
No meu caso, o mangusto não relata erro após connectTimeoutMS
no bloco catch
. Estou usando o Mongodb 3.6.5 e o mangusto 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 apenas para confirmar, você está se conectando a uma instância mongodb autônoma ou a um conjunto de réplicas?
@vkarpov15 Estou usando instância autônoma.
@ nvtuan305 qual sistema operacional? Além disso, por que você espera que o Mongoose não consiga se conectar ao autônomo - a instância mongod
inativa, não há conexão de rede, algo mais?
O script abaixo funciona como esperado:
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}`); });
}
Saída
$ 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
Ei, parece básico, mas por favor, verifique essas instruções
eu resolvo fazendo isso
Comentários muito úteis
Apenas para confirmar para quem vem mais tarde, isso funciona como esperado: