Comment gérer l'erreur mongoose.connect()
dans le gestionnaire de capture ? Je souhaite utiliser la chaîne d'initialisation de l'application mais je ne peux pas le faire car mongoose.connect()
ne renvoie pas la promesse rejetée. Il ne renvoie la promesse rejetée que si je spécifie le rappel, mais ce n'est pas une solution parfaite.
Exemple:
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);
});
Solution de contournement:
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);
});
Je pense que mongoose.connect()
génère une erreur asynchrone au lieu de renvoyer une promesse rejetée afin de ne pas rompre la compatibilité descendante. Les utilisateurs s'attendent à ce que l'application se termine avec un code d'erreur si quelque chose ne va pas avec l'établissement de la connexion Mangoose. Si mongoose.connect()
renvoie la demande de promesse rejetée se terminera avec le code 0 et rien ne sera sorti sur la console. Il sera donc bon d'avoir un moyen de dire mongoose.connect()
pour retourner la promesse. Peut-être quelque chose comme 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 Que
@Jokero désolé mec.......
Utilisez le rappel de mongoose.connect pour détecter toute erreur lors de la connexion.
Vous pouvez démarrer votre serveur en cas d'ouverture.
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 je sais, je peux utiliser le rappel pour la gestion des erreurs mais le problème concerne les promesses :smiley:
N'utilisez pas la promesse de mongoose.connect, démarrez votre serveur lorsque la connexion est ouverte pour la première fois (.once('open'))
Pourquoi? Aucune différence du tout. Lorsque la connexion est ouverte, le rappel mongoose.connect
sera appelé ainsi que la promesse retournée sera remplie et l'événement open
sera émis. Donc tu peux utiliser ce que tu veux
Oui mais comme vous l'avez dit, mongoose.connect a besoin d'un rappel en cas d'erreur.
C'est pourquoi j'ai créé ce problème :smiley:
J'ai le même problème.
J'aimerais pouvoir utiliser mongoose.connect(...).catch(failCallback)
mais lorsqu'une erreur se produit lors de la tentative de connexion initiale, failCallback
ne s'exécute pas. Il y a quelque chose de mal avec le MongooseThenable
pseudo-promesse mongoose.connect
retours. De plus, j'ai configuré mongoose.Promise = require('bluebird')
et je m'attends vraiment à ce que de tels appels asynchrones renvoient une _réelle_ promesse, une Bluebird dans mon cas.
Le problème avec mon failCallback
ne s'exécute pas, cependant, ne se produit qu'au début, c'est-à-dire :
// 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);
});
Mais effectivement ça marche comme ça (ce qui n'a pas de sens) :
// 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
Pourquoi donc?
Re : retourner une vraie promesse, c'est comme ça pour la rétrocompatibilité. Malheureusement, les gens s'appuient sur le comportement de chaînage de .connect()
pour une raison quelconque (#3847, #3790, etc.), nous le gardons donc pour l'instant :) Ajout d'un correctif afin que .catch()
puisse attraper la connexion initiale problèmes.
Ça marche! Mais ces changements casseront-ils quelque chose pour ceux qui s'attendent à ce que le processus de candidature soit terminé lorsqu'une erreur de connexion se produit et qu'il n'y a pas de gestionnaires de rappel et de promesse ?
Exemple:
const mongoose = require('mongoose');
mongoose.Promise = Promise;
mongoose.connect('mongodb://127.0.0.2/test'); // no callback and promise handlers
Avant ces changements
/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)
Avec ces changements, le processus est terminé avec 0 code
Merci pour la suggestion, va étudier.
Cool! Merci :+1:
+1
J'adorerais pouvoir retourner le résultat de .connect() en tant que promesse à part entière dans le chaînage d'initialisation.
@CodeJjang ça ne marche pas déjà ? Cette fonctionnalité a déjà été publiée
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);
});
Cela ne fonctionne pas pour moi :(
Cela montre
(node:22564) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: failed to connect to server [127.0.0.1:27017] on first connect
Hmm, essayez de vous débarrasser du rappel dans mongoose.connect()
Je viens de recevoir:
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1):
MongoError: failed to connect to server [localhost:17551] on first connect
ne pas utiliser les promesses sur la mangouste 4.7.6 (la plus récente en ce moment), un moyen d'éviter cet avertissement ?
Je l'utilise avec ExpressJS et si j'utilise catch, il bousille ma logique et se comporte bizarrement car express-session
crée aussi un MongoStore... tout simplement désordonné.
Exemple de code s'il vous plaît
J'ai le même problème que @matheo. Je viens d'ouvrir ce ticket :
Juste pour confirmer pour ceux qui viendront plus tard, cela fonctionne comme prévu :
mongoose.connect('http://127.0.0.1:27017/test')
.then(() => {
server.start();
})
.catch((err) => {
console.log('Error on start: ' + err.stack);
process.exit(1);
});
Juste pour confirmer pour ceux qui viendront plus tard, cela fonctionne comme prévu :
mongoose.connect('http://127.0.0.1:27017/test') .then(() => { server.start(); }) .catch((err) => { console.log('Error on start: ' + err.stack); process.exit(1); });
J'utilise aussi cette approche ! Mais lorsque j'arrête mongodb puis que j'exécute ce code, cela ne fonctionne pas.
// 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'entendez-vous par « ne fonctionne pas » ? Y a-t-il des messages d'erreur ?
@ vkarpov15 Je veux dire qu'aucune erreur ne sera imprimée
Procédure:
catch
ne sera pas atteint. // Never reach to here
console.log(err);
process.exit(1);
@nvtuan305 si la connexion initiale connectTimeoutMS
. Ce n'est pas le cas pour toi ? Si oui, quelle version de MongoDB et mongoose ?
@vkarpov15
mangouste signalera une erreur après
connectTimeoutMS
Dans mon cas, la mangouste ne signale pas d'erreur après connectTimeoutMS
au bloc catch
. J'utilise Mongodb 3.6.5 et 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 juste pour confirmer, vous connectez-vous à une instance mongodb autonome ou à un jeu de réplicas ?
@ vkarpov15 J'utilise une instance autonome.
@nvtuan305 quel système d'exploitation ? De plus, pourquoi pensez-vous que Mongoose ne parvient pas à se connecter à l'instance autonome ? L'instance mongod
est-elle en panne, n'y a-t-il pas de connexion réseau, autre chose ?
Le script ci-dessous fonctionne comme prévu :
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}`); });
}
Sortir
$ 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
Hé, cela semble basique mais veuillez vérifier ces instructions
je le résous en faisant ça
Commentaire le plus utile
Juste pour confirmer pour ceux qui viendront plus tard, cela fonctionne comme prévu :