Как сделать синхронный запрос БД перед запуском приложения асинхронного узла? - PullRequest
0 голосов
/ 10 января 2020

Я запускаю приложение узла с CORS. В настоящее время я загружаю белые списки доменов из файла .env, но мне нужно изменить его, чтобы загрузить их из базы данных. Вся функциональность CORS синхронна, и мне интересно, как правильно сделать для нее запрос в БД.

app. js

app.use(cors());

async function listenCallback(server) {
try {
    // app code
} catch (err) {
    server.close();
}

cors. js

const cors = require('cors');
const db = require('../db');


const whitelist = db.raw('select domains from table'); // I need to change this


module.exports = (enabled = true) =>
    (req, res, next) => {
        const options = {
            origin(origin, callback) {
                if (!origin) {
                    callback(null, true);
                    return;
                }
                const originIsWhitelisted = enabled ? whitelist.indexOf(origin) !== -1 : true;
                if (originIsWhitelisted) {
                    callback(null, originIsWhitelisted);
                    return;
                }
                callback({
                    statusCode: 401,
                    error: 'Not allowed',
                });
            },
        };
        return cors(options)(req, res, next);
    };

1 Ответ

1 голос
/ 10 января 2020

Если вы пытаетесь загрузить набор доменов из базы данных при инициализации модуля, чтобы затем использовать их в некотором промежуточном программном обеспечении, тогда вы можете получить обещание, загрузив whilelist из базы данных, а затем просто используйте это обещание в вашем промежуточном программном обеспечении.

const cors = require('cors');
const db = require('../db');

const whitelistPromise = db.someOperationThatReturnsPromise();

module.exports = (enabled = true) =>
    (req, res, next) => {
        const options = {
            origin(origin, callback) {
                if (!origin) {
                    callback(null, true);
                    return;
                }
                whitelistPromise.then(whitelist => {
                    const originIsWhitelisted = enabled ? whitelist.indexOf(origin) !== -1 : true;
                    if (originIsWhitelisted) {
                        callback(null, originIsWhitelisted);
                        return;
                    }
                    callback({
                        statusCode: 401,
                        error: 'Not allowed',
                    });
                }).catch(err => {
                    console.log(err);
                    next(err);
                    return;
                });
            },
        };
        return cors(options)(req, res, next);
    };

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

const cors = require('cors');
const db = require('../db');

// export module constructor that initializes this module asynchronously and returns a promise
// That promise resolves to the middleware function (so it can't be used before
// the module is properly initialized)
module.exports = function() {
    return db.someOperationThatReturnsPromise().then(whitelist => {
        return (enabled = true) => (req, res, next) => {
            const options = {
                origin(origin, callback) {
                    if (!origin) {
                        callback(null, true);
                        return;
                    }
                    const originIsWhitelisted = enabled ? whitelist.indexOf(origin) !== -1 : true;
                    if (originIsWhitelisted) {
                        callback(null, originIsWhitelisted);
                        return;
                    }
                    callback({
                        statusCode: 401,
                        error: 'Not allowed',
                    });
                },
            };
            return cors(options)(req, res, next);
        };
    });
}

В этом случае любой, кто загрузит этот модуль, сделает это примерно так:

require('./myModule')().then(makeWhitelistMiddleware => {
    // put route handlers here that use the function to make CORS middleware
    // don't start your server until this completes
    app.use(makeWhitelistMiddleware());
    // other routes here
    app.get(...)
    // start server
    app.listen(...);
}).catch(err => {
    console.log("Could not initialize myModule");
    process.exit(1);
});

Наконец, я добавлю, что в настоящее время предпринимаются усилия для обеспечения верхнего уровня await внутри инициализации модуля, где вся система загрузчика модулей может быть осведомлена об обещаниях, связанных с инициализацией модуля. , Возможность такого типа значительно упростит эту задачу, но до этого вам придется добавлять собственный код для другой инициализации модуля и другой загрузки модуля.

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