Как заставить nodejs ждать подключения к mongodb перед продолжением (блокировка asyn c) - PullRequest
0 голосов
/ 23 февраля 2020

Я хочу, чтобы мое приложение nodejs не продолжало работать, пока оно не подключится к mongodb.

Я попытался:

//Mongo
async function mongoConnect(mongoDB) {
    var mongoConnectionSuccessful = false;
    LOG("Connecting to mongodb at " + mongoDB + "...");
    while (!mongoConnectionSuccessful) {
        try {
            await mongoose.connect(mongoDB, { useNewUrlParser: true, useUnifiedTopology: true });
            LOG("connected!");
            mongoConnectionSuccessful = true;
            mongoose.connection.on('error', ()=>LOG('MongoDB connection error:'));
            return;
        } catch (error) {
            LOG(error);
        }
        await utils.sleep(500);
    }
}
mongoConnect(config.mongoUrl);

, но для использования await в mongoose.connect, Я должен сделать mongConnect async, но затем я не могу вызвать его блокирующим способом из кода, потому что для такого вызова я должен вызывать с await, но ожидание разрешено только внутри функций asyn c .

Ответы [ 4 ]

1 голос
/ 23 февраля 2020

Я должен вызывать с ожиданием, но ожидание разрешено только внутри asyn c functions

Это правильно. Так что просто сделайте это:

async function main () {
    await mongoConnect(config.mongoUrl);

    // rest of your code...
}

main();

Например, если это Express сервер, сделайте что-то вроде:

const express = require('express');
const app = express();

async function main () {
    await mongoConnect(config.montoUrl);

    const routes = require('./my-routes');

    app.use(routes);
    app.listen(config.port);
}

main();
1 голос
/ 23 февраля 2020

Вы хотите попытаться восстановить соединение, если mongoose не удается подключиться. Вот пример logi c без вспомогательного lib.Props парню, который разместил это решение в проблеме github для mongoose. Здесь

function createConnection (dbURL, options) {
    var db = mongoose.createConnection(dbURL, options);

    db.on('error', function (err) {
        // If first connect fails because mongod is down, try again later.
        // This is only needed for first connect, not for runtime reconnects.
        // See: https://github.com/Automattic/mongoose/issues/5169
        if (err.message && err.message.match(/failed to connect to server .* on first connect/)) {
            console.log(new Date(), String(err));

            // Wait for a bit, then try to connect again
            setTimeout(function () {
                console.log("Retrying first connect...");
                db.openUri(dbURL).catch(() => {});
                // Why the empty catch?
                // Well, errors thrown by db.open() will also be passed to .on('error'),
                // so we can handle them there, no need to log anything in the catch here.
                // But we still need this empty catch to avoid unhandled rejections.
            }, 20 * 1000);
        } else {
            // Some other error occurred.  Log it.
            console.error(new Date(), String(err));
        }
    });

    db.once('open', function () {
        console.log("Connection to db established.");
    });

    return db;
}

// Use it like
var db = createConnection('mongodb://...', options);

и с библиотекой promise-retry

const promiseRetry = require('promise-retry')

const options = {
  useNewUrlParser: true,
  reconnectTries: 60,
  reconnectInterval: 1000,
  poolSize: 10,
  bufferMaxEntries: 0 // If not connected, return errors immediately rather than waiting for reconnect
}

const promiseRetryOptions = {
  retries: options.reconnectTries,
  factor: 2,
  minTimeout: options.reconnectInterval,
  maxTimeout: 5000
}

const connect = () => {
  return promiseRetry((retry, number) => {
    logger.info(`MongoClient connecting to ${url} - retry number: ${number}`)
    return MongoClient.connect(url, options).catch(retry)
  }, promiseRetryOptions)
}

module.exports = { connect }
0 голосов
/ 24 февраля 2020

Я предполагаю, что по какой-то причине у вас есть входящие события, в то время как вы пытаетесь подключиться к mon go. Мой подход заключается в предотвращении любых входящих событий (таких как запуск сервера и настройка прослушивателей) перед подключением к mon go. Если это невозможно, один из способов сделать это - использовать функцию, вызывающую себя.

//Mongo
async function mongoConnect(mongoDB) {
    var mongoConnectionSuccessful = false;
    LOG("Connecting to mongodb at " + mongoDB + "...");
    while (!mongoConnectionSuccessful) {
        try {
            await mongoose.connect(mongoDB, { useNewUrlParser: true, useUnifiedTopology: true });
            LOG("connected!");
            mongoConnectionSuccessful = true;
            mongoose.connection.on('error', ()=>LOG('MongoDB connection error:'));
            return;
        } catch (error) {
            LOG(error);
        }
        await utils.sleep(500);
    }
}

(async function() {
  // do stuff
  await mongoConnect(config.mongoUrl);
  // do other stuff
})();
0 голосов
/ 23 февраля 2020

Я нашел решение в этой статье

Я полагаю, что вам нужно обещать ваш вызов mongoConnect (config.mongoUrl),
, чем ждать обещаний, пока он не будет вызван назад.

async function getConcurrently() { 
    let promises = []; 
    promises.push(mongoConnect(config.mongoUrl))
    // promises.push(getUsers()); 
    // promises.push(getCategories()); 
    // promises.push(getProducts());

    let mongo = await Promise.all(promises);
    //let [users, categories, products] = await Promise.all(promises); 
}

Обратите внимание на это предупреждение в статье:

В качестве первого примера сначала мы создаем массив Promises (каждая из функций get является Promise ). Затем мы выполняем их все одновременно и одновременно, ожидая, пока все они завершатся sh (ожидают Promise.all). Наконец, мы присваиваем результаты соответствующим переменным пользователям, категориям и продуктам. Несмотря на то, что это работает, важно сказать, что использование Promises.all () для всего - плохая идея.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...