Является ли создание нового обещания с вызовом асинхронной функции плохой практикой? - PullRequest
0 голосов
/ 27 мая 2018

Фрагменты взяты из CRUD-приложения node.js и mongoDB. Репозиторий Github для полного кода. Код работает нормально, но не уверен, что моя структура и использование обещаний и асинхронного ожидания являются плохой практикой.

handlers._newbies = {};

handlers._newbies.post = (parsedReq, res) => {

    const newbie = JSON.parse(parsedReq.payload);
    databaseCalls.create(newbie)
        .then((result) => {
            res.writeHead(200,{'Content-Type' : 'application/json'});
            const resultToString = JSON.stringify(result.ops[0]);
            res.write(resultToString);
            res.end();
        })
        .catch(err => console.log(err));
};


const databaseCalls = {};

databaseCalls.create = (newbie) => {
    return new Promise(async (resolve, reject) => {
        try {
            const client = await MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true });
            console.log("Connected correctly to server");
            const db = client.db('Noob-List');
            const result = await db.collection('newbies').insertOne(newbie);
            client.close();
            resolve(result);
        } catch(err) {
            console.log(err);
        }
    });
};

Когда сервер узла получает запрос POST с полезной нагрузкой JSON, он вызывает обработчик handlers._newbies.post, который принимает полезную нагрузку и передает ее вызову

const newbie = JSON.parse(parsedReq.payload);
databaseCalls.create(newbie)

.Я хочу, чтобы этот вызов базы данных возвращал обещание, которое содержит результат вызова db.collection('newbies').insertOne(newbie);.У меня были проблемы с этим, когда я просто возвращал обещание, возвращаемое insertOne, потому что после возвращения я не могу позвонить client.close();.

Опять, может, то, что я сделал здесь, хорошо, но я ничего не нашел в Интернете о созданииобещания с обещаниями в них.Спасибо за ваше время, дайте мне знать, что неясно с моим вопросом.

1 Ответ

0 голосов
/ 27 мая 2018

Считается, что анти-шаблон заключает в себе существующее обещание в обещании, созданном вручную, потому что для этого просто нет причин, и это создает много возможностей для ошибок, особенно в обработке ошибок.

ИВ вашем случае у вас есть несколько проблем с обработкой ошибок.

  1. Если вы обнаружите ошибку где-либо в коде вашей базы данных, вы никогда не разрешите или не отклоните созданное вами обещание.Это классическая проблема с анти-паттерном.
  2. Если после открытия БД появляется ошибка, вы не закрываете БД
  3. Вы не сообщаете об ошибкевызывающий абонент.

Вот как вы можете выполнить свою функцию .create() без анти-паттерна и без вышеуказанных проблем:

databaseCalls.create = async function(newbie) {
    let client;
    try {
        client = await MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true });
        console.log("Connected correctly to server");
        const db = client.db('Noob-List');
        return db.collection('newbies').insertOne(newbie);
    } catch(err) {
        // log error, but still reject the promise
        console.log(err);
        throw err;
    } finally {
        // clean up any open database
        if (client) {
            client.close();
        }
    }
}

Тогда вы будете использовать это как:

databaseCalls.create(something).then(result => {
    console.log("succeeded");'
}).catch(err => {
    console.log(err);
});

К вашему сведению, я также изменил некоторые другие вещи:

  1. Соединение с базой данных закрыто, даже в условиях ошибки
  2. Функция возвращает обещание, которое разрешенос результатом .insertOne() (если есть значимый результат)
  3. Если есть ошибка, возвращенное обещание отклоняется с этой ошибкой

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

...