Mongoose: Methode zur Behandlung des mongoose.connect()-Fehlers im Promise-Catch-Handler

Erstellt am 10. Mai 2016  ·  31Kommentare  ·  Quelle: Automattic/mongoose

Wie behandelt man den mongoose.connect() Fehler im Catch-Handler? Ich möchte die Anwendungsinitialisierungskette verwenden, kann dies jedoch nicht, da mongoose.connect() kein abgelehntes Versprechen zurückgibt. Es gibt nur abgelehnte Zusagen zurück, wenn ich Rückruf angebe, aber es ist keine perfekte Lösung.

Beispiel:

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);
    });

Problemumgehung:

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);
    });

Ich denke, mongoose.connect() löst einen asynchronen Fehler aus, anstatt ein abgelehntes Versprechen zurückzugeben, um die Abwärtskompatibilität nicht zu beeinträchtigen. Benutzer erwarten, dass die Anwendung mit einem Fehlercode beendet wird, wenn bei der Herstellung der Mungo-Verbindung etwas schief gelaufen ist. Wenn mongoose.connect() abgelehnte Zusage zurückgibt, wird die Anwendung mit 0-Code beendet und es wird nichts an die Konsole ausgegeben. Es ist also gut, eine Möglichkeit zu haben, mongoose.connect() zu sagen, um das Versprechen zurückzugeben. Vielleicht so etwas wie 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

Hilfreichster Kommentar

Nur zur Bestätigung für alle, die später kommen, funktioniert dies wie erwartet:

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

Alle 31 Kommentare

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 Was meinst du? :smiley: Ich möchte keinen Rückruf verwenden)

@Jokero Entschuldigung, Alter......... habe deine Frage falsch verstanden. :)

Verwenden Sie den Rückruf von mongoose.connect, um Fehler während der Verbindung abzufangen.
Sie können Ihren Server im Ereignis öffnen starten.

        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 Ich weiß, ich kann Callback für die Fehlerbehandlung verwenden, aber das Problem

Verwenden Sie nicht das Versprechen von mongoose.connect, starten Sie Ihren Server, wenn die Verbindung zum ersten Mal geöffnet ist (.once('open'))

Wieso den? Überhaupt kein Unterschied. Wenn die Verbindung geöffnet wird, wird mongoose.connect Callback aufgerufen, sowie das zurückgegebene Versprechen erfüllt und open Event ausgegeben. Du kannst also verwenden, was du willst

Ja, aber wie gesagt, mongoose.connect braucht im Fehlerfall einen Rückruf.

Deshalb habe ich dieses Problem erstellt :smiley:

Ich habe das gleiche Problem.

Ich möchte mongoose.connect(...).catch(failCallback) aber wenn beim ersten Verbindungsversuch ein Fehler auftritt, wird failCallback nicht ausgeführt. Etwas stimmt nicht mit dem MongooseThenable Pseudoversprechen, das mongoose.connect zurückgibt. Außerdem habe ich mongoose.Promise = require('bluebird') konfiguriert und ich erwarte wirklich, dass solche asynchronen Aufrufe ein _echtes_ Versprechen zurückgeben, in meinem Fall ein Bluebird-Versprechen.

Das Problem, dass mein failCallback nicht ausgeführt wird, tritt jedoch nur anfänglich auf, dh:

// 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);
});

Aber es funktioniert tatsächlich so (was unsinnig ist):

// 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

Warum ist das so?

Re: Ein echtes Versprechen zurückgeben, es ist so für die Abwärtskompatibilität. Leider Menschen verlassen sich auf .connect() aus irgendeinem Grunde Verhalten Chaining (# 3847, # 3790, etc.) , so dass wir es auf diese Weise für jetzt halten sind :) Hinzugefügt ein Update so .catch() können anfängliche Verbindung fangen Probleme.

Es klappt! Aber werden diese Änderungen etwas für diejenigen bedeuten, die erwarten, dass der Bewerbungsprozess abgeschlossen ist, wenn ein Verbindungsfehler auftritt und es keine Callback- und Promise-Handler gibt?

Beispiel:

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

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

Vor diesen Änderungen

/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)

Mit diesen Änderungen ist der Vorgang mit 0 Code abgeschlossen

Danke für den Vorschlag, werde nachforschen.

Cool! Danke :+1:

+1
Würde gerne das Ergebnis von .connect() als vollwertiges Promise in der Initialisierungsverkettung zurückgeben.

@CodeJjang funktioniert das nicht schon? Diese Funktion wurde bereits freigegeben

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);
    });

Das funktioniert bei mir nicht :(
Es zeigt
(node:22564) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: failed to connect to server [127.0.0.1:27017] on first connect

Hmm, versuchen Sie, den Rückruf in mongoose.connect() loszuwerden

Ich habe gerade:

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

keine Versprechungen für Mungo 4.7.6 (aktuell aktuell) verwenden, gibt es eine Möglichkeit, diese Warnung zu vermeiden?
Ich verwende es mit ExpressJS und wenn ich catch verwende, verdreht es meine Logik und verhält sich seltsam, da express-session einen MongoStore erstellt ... einfach chaotisch.

Codebeispiel bitte

Ich habe das gleiche Problem wie @matheo. Habe gerade dieses Ticket geöffnet:

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

Nur zur Bestätigung für alle, die später kommen, funktioniert dies wie erwartet:

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

Nur zur Bestätigung für alle, die später kommen, funktioniert dies wie erwartet:

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

Diesen Ansatz verwende ich auch! Aber wenn ich mongodb beende und dann diesen Code ausführe, funktioniert es nicht.

// 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 was meinst du mit "funktioniert nicht"? Gibt es einige Fehlermeldungen?

@vkarpov15 Ich meine, es wird kein Fehler gedruckt

Verfahren:

  • Schritt 1: Ich habe den Mongodb-Dienst gestoppt
  • Schritt 2: Verbinden Sie sich mit mongodb. In diesem Schritt wird kein Fehler in die Konsole ausgegeben, der catch Block wird nicht erreicht.
    // Never reach to here
    console.log(err);
    process.exit(1);

@nvtuan305 Wenn die anfängliche Verbindung connectTimeoutMS einen Fehler. Ist das bei Ihnen nicht der Fall? Wenn ja, welche Version von MongoDB und Mongoose?

@vkarpov15

Mungo meldet einen Fehler nach connectTimeoutMS

In meinem Fall meldet Mungo keinen Fehler nach connectTimeoutMS im catch Block. Ich verwende Mongodb 3.6.5 und Mungo 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 nur zur Bestätigung, stellen Sie eine Verbindung zu einer eigenständigen Mongodb-Instanz oder einem Replikatsatz her?

@vkarpov15 Ich verwende eine eigenständige Instanz.

@nvtuan305 welches Betriebssystem? Außerdem, warum erwarten Sie, dass Mongoose keine Verbindung zum Standalone-Gerät herstellen kann - ist die Instanz mongod ausgefallen, besteht keine Netzwerkverbindung oder etwas anderes?

Das folgende Skript funktioniert wie erwartet:

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}`); });
}

Ausgabe

$ 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

Hey, es scheint einfach, aber bitte überprüfen Sie diese Anweisungen noch einmal

  • Legen Sie Ihre IP-Adresse auf dem Mongo-Cluster fest, Sie können sogar den Zugriff von überall einstellen
  • Achten Sie darauf, Fehler zu behandeln, zum Beispiel mit Catch

Ich löse es damit

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen