Mongoose: Cara menangani kesalahan mongoose.connect() di penangan janji catch

Dibuat pada 10 Mei 2016  ·  31Komentar  ·  Sumber: Automattic/mongoose

Bagaimana menangani kesalahan mongoose.connect() di catch handler? Saya ingin menggunakan rantai inisialisasi aplikasi tetapi tidak dapat melakukannya karena mongoose.connect() tidak mengembalikan janji yang ditolak. Ini mengembalikan janji yang ditolak hanya jika saya menentukan panggilan balik, tetapi itu bukan solusi yang sempurna.

Contoh:

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

Solusi:

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

Saya pikir mongoose.connect() melempar kesalahan async alih-alih mengembalikan janji yang ditolak agar tidak merusak kompatibilitas ke belakang. Pengguna berharap aplikasi akan selesai dengan kode kesalahan jika terjadi kesalahan dengan pembuatan koneksi luwak. Jika mongoose.connect() mengembalikan aplikasi janji yang ditolak akan selesai dengan kode 0 dan tidak ada yang akan ditampilkan ke konsol. Jadi akan baik untuk memiliki beberapa cara untuk mengatakan mongoose.connect() untuk membalas janji. Mungkin sesuatu seperti 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

Komentar yang paling membantu

Hanya untuk mengonfirmasi siapa pun yang datang nanti, ini berfungsi seperti yang diharapkan:

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

Semua 31 komentar

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 Apa maksudmu? :smiley: Saya tidak ingin menggunakan panggilan balik)

@Jokero maaf Bung ......... salah paham pertanyaan Anda. :)

Gunakan panggilan balik luwak.connect untuk menangkap kesalahan apa pun selama koneksi.
Anda dapat memulai server Anda di acara terbuka.

        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 Saya tahu, saya dapat menggunakan panggilan balik untuk penanganan kesalahan tetapi masalahnya adalah tentang janji: smiley:

Jangan gunakan janji dari luwak.connect, mulai server Anda saat koneksi terbuka untuk pertama kalinya (.once('open'))

Mengapa? Tidak ada perbedaan sama sekali. Ketika koneksi dibuka, mongoose.connect callback akan dipanggil serta janji yang dikembalikan akan dipenuhi dan event open akan dipancarkan. Jadi Anda dapat menggunakan apa yang Anda inginkan

Ya, tetapi seperti yang Anda katakan, luwak.connect membutuhkan panggilan balik jika terjadi kesalahan.

Itu sebabnya saya membuat masalah ini :smiley:

Saya memiliki masalah yang sama.

Saya ingin dapat menggunakan mongoose.connect(...).catch(failCallback) tetapi ketika terjadi kesalahan pada upaya koneksi awal failCallback tidak dijalankan. Ada yang salah dengan MongooseThenable pseudo-promise yang dikembalikan oleh mongoose.connect . Selain itu, saya telah mengonfigurasi mongoose.Promise = require('bluebird') dan saya sangat mengharapkan panggilan async seperti itu untuk mengembalikan janji _real_, Bluebird dalam kasus saya.

Masalah dengan failCallback tidak dieksekusi, bagaimanapun, hanya terjadi pada awalnya, yaitu:

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

Tapi memang itu bekerja seperti itu (yang tidak masuk akal):

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

Mengapa demikian?

Re: mengembalikan janji nyata, begitulah untuk kompatibilitas ke belakang. Sayangnya orang-orang mengandalkan .connect() perilaku berantai untuk beberapa alasan (#3847, #3790, dll) jadi kami tetap seperti ini untuk saat ini :) Menambahkan perbaikan sehingga .catch() dapat menangkap koneksi awal masalah.

Berhasil! Tetapi apakah perubahan ini akan merusak sesuatu bagi mereka yang mengharapkan proses aplikasi akan selesai ketika kesalahan koneksi terjadi dan tidak ada penangan panggilan balik dan janji?

Contoh:

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

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

Sebelum perubahan ini

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

Dengan proses perubahan ini selesai dengan 0 kode

Terima kasih atas sarannya, akan diselidiki.

Dingin! Terima kasih :+1:

+1
Akan senang jika dapat mengembalikan hasil .connect() sebagai Janji penuh dalam rantai inisialisasi.

@CodeJjang apakah ini belum berfungsi? Fungsionalitas ini telah dirilis

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

Ini tidak bekerja untuk saya :(
Ini menunjukkan
(node:22564) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: failed to connect to server [127.0.0.1:27017] on first connect

Hmm coba singkirkan panggilan balik di mongoose.connect()

Saya baru saja dapat:

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

tidak menggunakan janji di luwak 4.7.6 (terbaru sekarang), ada cara untuk menghindari Peringatan itu?
Saya menggunakannya dengan ExpressJS dan jika saya menggunakan catch, itu mengacaukan logika saya dan berperilaku aneh karena express-session juga membuat MongoStore... hanya berantakan.

Tolong contoh kodenya

Saya memiliki masalah yang sama dengan @mateo. Baru saja membuka tiket ini:

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

Hanya untuk mengonfirmasi siapa pun yang datang nanti, ini berfungsi seperti yang diharapkan:

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

Hanya untuk mengonfirmasi siapa pun yang datang nanti, ini berfungsi seperti yang diharapkan:

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

Saya juga menggunakan pendekatan ini! Tetapi ketika saya menghentikan mongodb lalu menjalankan kode ini, itu tidak berfungsi.

// 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 apa yang Anda maksud dengan 'tidak berfungsi'? Apakah ada beberapa pesan kesalahan?

@vkarpov15 Maksud saya tidak ada kesalahan yang akan dicetak

Prosedur:

  • Langkah 1: Saya menghentikan layanan mongodb
  • Langkah 2: Terhubung dengan mongodb. Pada langkah ini, tidak ada kesalahan yang akan dicetak ke konsol, blok catch tidak akan tercapai.
    // Never reach to here
    console.log(err);
    process.exit(1);

@nvtuan305 jika koneksi awal habis, luwak akan melaporkan kesalahan setelah connectTimeoutMS . Apakah itu tidak berlaku untuk Anda? Jika ya, MongoDB dan luwak versi berapa?

@vkarpov15

luwak akan melaporkan kesalahan setelah connectTimeoutMS

Dalam kasus saya, luwak tidak melaporkan kesalahan setelah connectTimeoutMS di catch blok. Saya menggunakan Mongodb 3.6.5 dan luwak 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 hanya untuk mengonfirmasi, apakah Anda terhubung ke instance mongodb mandiri atau set replika?

@vkarpov15 Saya menggunakan contoh mandiri.

@nvtuan305 sistem operasi apa? Juga, mengapa Anda mengharapkan Mongoose gagal terhubung ke standalone - apakah instance mongod down, apakah tidak ada koneksi jaringan, sesuatu yang lain?

Skrip di bawah ini berfungsi seperti yang diharapkan:

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

Keluaran

$ 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

Hei, tampaknya dasar tapi tolong periksa kembali petunjuk ini

  • Atur Alamat IP Anda di cluster Mongo, Anda bahkan dapat mengatur akses dari mana saja
  • Pastikan untuk menangani kesalahan, dengan tangkapan misalnya

Saya menyelesaikannya dengan melakukan itu

Apakah halaman ini membantu?
0 / 5 - 0 peringkat