Mongoose: Promise catch ν•Έλ“€λŸ¬μ—μ„œ mongoose.connect() 였λ₯˜λ₯Ό μ²˜λ¦¬ν•˜λŠ” 방법

에 λ§Œλ“  2016λ…„ 05μ›” 10일  Β·  31μ½”λ©˜νŠΈ  Β·  좜처: Automattic/mongoose

catch ν•Έλ“€λŸ¬μ—μ„œ 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 무슨

@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의 약속을 μ‚¬μš©ν•˜μ§€ 말고 연결이 처음 열릴 λ•Œ μ„œλ²„λ₯Ό μ‹œμž‘ν•˜μ‹­μ‹œμ˜€(.once('open'))

μ™œμš”? μ „ν˜€ 차이가 μ—†μŠ΅λ‹ˆλ‹€. 연결이 열리면 mongoose.connect 콜백이 호좜되고 λ°˜ν™˜λœ promiseκ°€ μ΄ν–‰λ˜κ³  open μ΄λ²€νŠΈκ°€ λ°œμƒν•©λ‹ˆλ‹€. μ›ν•˜λŠ” 것을 μ‚¬μš©ν•  수 μžˆλ„λ‘

λ„€, ν•˜μ§€λ§Œ λ§μ”€ν•˜μ‹  λŒ€λ‘œ mongoose.connectλŠ” 였λ₯˜κ°€ λ°œμƒν•  경우 콜백이 ν•„μš”ν•©λ‹ˆλ‹€.

이것이 μ œκ°€ 이 문제λ₯Ό λ§Œλ“  μ΄μœ μž…λ‹ˆλ‹€ :슀마일리:

같은 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€.

mongoose.connect(...).catch(failCallback) 을(λ₯Ό) μ‚¬μš©ν•˜κ³  μ‹Άμ§€λ§Œ 초기 μ—°κ²° μ‹œλ„ μ‹œ 였λ₯˜κ°€ λ°œμƒν•˜λ©΄ failCallback κ°€ μ‹€ν–‰λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. mongoose.connect λ°˜ν™˜ν•˜λŠ” MongooseThenable μ˜μ‚¬ 약속에 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€. κ²Œλ‹€κ°€ μ €λŠ” mongoose.Promise = require('bluebird') ν–ˆκ³  κ·ΈλŸ¬ν•œ 비동기 호좜이 제 κ²½μš°μ—λŠ” Bluebird 약속인 _real_ 약속을 λ°˜ν™˜ν•  κ²ƒμœΌλ‘œ μ •λ§λ‘œ κΈ°λŒ€ν•©λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ λ‚΄ 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

μ™œ 그런 κ²λ‹ˆκΉŒ?

Re: μ‹€μ œ 약속을 λ°˜ν™˜ν•˜λŠ” 것은 이전 λ²„μ „κ³Όμ˜ ν˜Έν™˜μ„±μ„ μœ„ν•œ λ°©λ²•μž…λ‹ˆλ‹€. λΆˆν–‰νžˆλ„ μ‚¬λžŒλ“€μ€ μ–΄λ–€ 이유둜(#3847, #3790 λ“±) .connect() μ—°κ²° λ™μž‘μ— μ˜μ‘΄ν•˜λ―€λ‘œ μ§€κΈˆμ€ 이 방식을 μœ μ§€ν•©λ‹ˆλ‹€ :) .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()의 κ²°κ³Όλ₯Ό μ™„μ „ν•œ Promise둜 λ°˜ν™˜ν•  수 있기λ₯Ό μ›ν•©λ‹ˆλ‹€.

@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

mongoose 4.7.6(ν˜„μž¬ μ΅œμ‹  버전)μ—μ„œ 약속을 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 경우 κ²½κ³ λ₯Ό ν”Όν•  수 μžˆλŠ” 방법이 μžˆμŠ΅λ‹ˆκΉŒ?
ExpressJS와 ν•¨κ»˜ μ‚¬μš©ν•˜κ³  μžˆλŠ”λ° catchλ₯Ό μ‚¬μš©ν•˜λ©΄ 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 초기 μ—°κ²° μ‹œκ°„μ΄ 초과되면 mongooseλŠ” connectTimeoutMS 이후에 였λ₯˜λ₯Ό λ³΄κ³ ν•©λ‹ˆλ‹€. λ‹Ήμ‹ μ—κ²ŒλŠ” 그렇지 μ•ŠμŠ΅λ‹ˆκΉŒ? κ·Έλ ‡λ‹€λ©΄ MongoDB와 mongoose의 버전은 λ¬΄μ—‡μž…λ‹ˆκΉŒ?

@vkarpov15

mongooseλŠ” connectTimeoutMS 후에 였λ₯˜λ₯Ό λ³΄κ³ ν•©λ‹ˆλ‹€.

제 경우 λͺ½κ΅¬μŠ€λŠ” catch λΈ”λ‘μ—μ„œ connectTimeoutMS 이후에 였λ₯˜λ₯Ό λ³΄κ³ ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ €λŠ” 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

어이, 기본적인 것 κ°™μ§€λ§Œ 이 지침을 λ‹€μ‹œ ν™•μΈν•˜μ‹­μ‹œμ˜€.

  • Mongo ν΄λŸ¬μŠ€ν„°μ— IP μ£Όμ†Œλ₯Ό μ„€μ •ν•˜λ©΄ μ–΄λ””μ„œλ‚˜ μ•‘μ„ΈμŠ€λ₯Ό μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 예λ₯Ό λ“€μ–΄ catchλ₯Ό μ‚¬μš©ν•˜μ—¬ 였λ₯˜λ₯Ό μ²˜λ¦¬ν•΄μ•Ό ν•©λ‹ˆλ‹€.

κ·Έλ ‡κ²Œ ν•΄μ„œ ν•΄κ²°

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰