Mongoose: طريقة للتعامل مع خطأ mongoose.connect () في معالج التقاط الوعد

تم إنشاؤها على ١٠ مايو ٢٠١٦  ·  31تعليقات  ·  مصدر: Automattic/mongoose

كيف يتم التعامل مع الخطأ mongoose.connect() في معالج الالتقاط؟ أريد استخدام سلسلة تهيئة التطبيق ولكن لا يمكنني فعل ذلك لأن mongoose.connect() لا يُرجع الوعد المرفوض. إنه يعيد الوعد المرفوض فقط إذا حددت رد الاتصال ، لكنه ليس حلاً مثاليًا.

مثال:

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

الحل:

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

أعتقد أن mongoose.connect() يتسبب في حدوث خطأ غير متزامن بدلاً من إرجاع الوعد المرفوض من أجل عدم كسر التوافق مع الإصدارات السابقة. يتوقع المستخدمون أن يتم الانتهاء من التطبيق برمز الخطأ إذا حدث خطأ ما في إنشاء اتصال النمس. إذا أعاد mongoose.connect() فسيتم إنهاء طلب الوعد المرفوض برمز 0 ولن يتم إخراج أي شيء إلى وحدة التحكم. لذلك سيكون من الجيد أن يكون لديك طريقة لقول mongoose.connect() لإعادة الوعد. ربما شيء مثل 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

التعليق الأكثر فائدة

فقط للتأكيد لأي شخص يأتي لاحقًا ، هذا يعمل كما هو متوقع:

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

ال 31 كومينتر

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 ماذا تقصد؟ : smiley: لا أريد استخدام رد الاتصال)

Jokero آسف المتأنق ......... أسأت فهم سؤالك. :)

استخدم استدعاء mongoose.connect للقبض على أي خطأ أثناء الاتصال.
يمكنك بدء تشغيل الخادم الخاص بك في هذا الحدث المفتوح.

        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 ، يمكنني استخدام رد الاتصال لمعالجة الأخطاء ولكن المسألة تتعلق بالوعود: مبتسم:

لا تستخدم الوعد من mongoose.connect ، ابدأ خادمك عندما يكون الاتصال مفتوحًا لأول مرة (. مرة واحدة ('مفتوح'))

لماذا ا؟ لا فرق على الإطلاق. عند فتح الاتصال ، سيتم استدعاء رد الاتصال mongoose.connect وكذلك الوعد المرتجع وسيتم إرسال حدث open . حتى تتمكن من استخدام ما تريد

نعم ولكن كما قلت ، يحتاج mongoose.connect إلى معاودة الاتصال في حالة حدوث خطأ.

لهذا السبب صنعت هذه المشكلة: مبتسم:

لدي نفس المشكلة.

أود أن أتمكن من استخدام mongoose.connect(...).catch(failCallback) ولكن عند حدوث خطأ عند محاولة الاتصال الأولية ، لا يتم تنفيذ failCallback . هناك شيء خاطئ مع MongooseThenable الزائفة الوعد الذي mongoose.connect العوائد. علاوة على ذلك ، قمت بتكوين mongoose.Promise = require('bluebird') وأتوقع حقًا أن تعيد مكالمات مثل المزامنة وعد _real_ ، وهو Bluebird في حالتي.

ومع ذلك ، فإن مشكلة عدم تنفيذ failCallback تحدث في البداية فقط ، على سبيل المثال:

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

لكنها في الواقع تعمل على هذا النحو (وهو أمر لا معنى له):

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

لماذا هذا؟

إعادة: إعادة الوعد الحقيقي ، هذه هي الطريقة للتوافق مع الإصدارات السابقة. لسوء الحظ ، يعتمد الأشخاص على سلوك التسلسل .connect() لسبب ما (# 3847 ، # 3790 ، وما إلى ذلك) ، لذلك نحن نحافظ عليه على هذا النحو في الوقت الحالي :) تمت إضافة إصلاح حتى يتمكن .catch() التقاط الاتصال الأولي مسائل.

إنها تعمل! ولكن هل ستؤدي هذه التغييرات إلى كسر شيء بالنسبة لأولئك الذين يتوقعون انتهاء عملية التطبيق عند حدوث خطأ في الاتصال وعدم وجود معالجات رد الاتصال والوعد؟

مثال:

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

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

قبل هذه التغييرات

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

مع هذه التغييرات تنتهي العملية برمز 0

شكرا على الاقتراح ، وسوف تحقق.

رائع! شكر: +1:

+1
أحب أن أكون قادرًا على إرجاع نتيجة .connect () كوعد كامل في تسلسل التهيئة.

CodeJjang ألا يعمل هذا بالفعل؟ تم إصدار هذه الوظيفة بالفعل

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

وهذا لا يعمل بالنسبة لي :(
تظهر
(node:22564) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: failed to connect to server [127.0.0.1:27017] on first connect

حسنًا ، حاول التخلص من رد الاتصال بـ mongoose.connect()

انا فقط حصلت:

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

لا تستخدم الوعود على النمس 4.7.6 (الأحدث حاليًا) ، هل من طريقة لتجنب هذا التحذير؟
أنا أستخدمه مع ExpressJS وإذا كنت أستخدمه ، فإنه يفسد منطقي ويتصرف بشكل غريب لأن express-session يقوم بإنشاء MongoStore أيضًا ... فقط فوضوي.

عينة رمز من فضلك

لدي نفس المشكلة مثل @ matheo. فتحت للتو هذه التذكرة:

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

فقط للتأكيد لأي شخص يأتي لاحقًا ، هذا يعمل كما هو متوقع:

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

فقط للتأكيد لأي شخص يأتي لاحقًا ، هذا يعمل كما هو متوقع:

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

أنا أستخدم هذا النهج أيضًا! لكن عندما أتوقف عن mongodb ثم شغّل هذا الكود ، فإنه لا يعمل.

// 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 ماذا تقصد ب "لا تعمل"؟ هل هناك بعض رسائل الخطأ؟

@ vkarpov15 أعني أنه لن تتم طباعة أي خطأ

إجراء:

  • الخطوة 1: توقفت عن خدمة mongodb
  • الخطوة 2: تواصل مع mongodb. في هذه الخطوة ، لن تتم طباعة أي خطأ في وحدة التحكم ، ولن يتم الوصول إلى الكتلة catch .
    // Never reach to here
    console.log(err);
    process.exit(1);

@ nvtuan305 إذا connectTimeoutMS . أليس هذا هو الحال بالنسبة لك؟ إذا كان الأمر كذلك ، ما هو إصدار MongoDB والنمس؟

هههههههههههههه

سيُبلغ النمس عن خطأ بعد connectTimeoutMS

في حالتي ، لا يبلغ النمس عن خطأ بعد كتلة connectTimeoutMS عند catch block. أنا أستخدم Mongodb 3.6.5 و 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 فقط للتأكيد ، هل تتصل بمثيل mongodb مستقل أو مجموعة متماثلة؟

@ vkarpov15 أنا أستخدم مثيل مستقل.

@ nvtuan305 ما نظام التشغيل؟ أيضًا ، لماذا تتوقع أن يفشل Mongoose في الاتصال بالمستقل - هل مثيل mongod معطل ، ألا يوجد اتصال بالشبكة ، شيء آخر؟

يعمل البرنامج النصي أدناه كما هو متوقع:

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

انتاج |

$ 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

مرحبًا ، يبدو الأمر أساسيًا ولكن يرجى التحقق مرة أخرى من تعليمات الأطروحات

  • قم بتعيين عنوان IP الخاص بك على مجموعة Mongo ، حتى يمكنك تعيين الوصول من كل مكان
  • تأكد من التعامل مع الأخطاء ، مع الصيد على سبيل المثال

أنا حلها بفعل ذلك

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات