NodeJS: MongoDB callback VS async/await

Odjakživa co píšu v NodeJS se držím callbackového zápisu asynchronních funkcí. Callback-hellu se snažím vyhnout rozumnou dekompozicí řešené úlohy a Promises zápis mě nikdy nedostal… Nicméně s jazykovou konstrukcí async/await, která se do JavaScriptu dostala ve verzi ES2017, se dá leckdy kód napsat čitelněji, pochopitelněji a tím pádem snad i bezpečněji.

Takhle by tedy mohl vypadat kód pro čtení dat z MongoDB:

Původní callback implementace

// nejake Expressjs obsluha routy, ktera cte z databaze uzivatele
const MongoClient = require('mongodb').MongoClient;

function getUsers(req, res) {
    MongoClient.connect(process.env.MONGOURL, { useNewUrlParser: true }, (err, client) => {
        if (err) {
            res.status(501).json({
                msg: 'mongodb connect error',
                detail: err.message
            });
        } else {
            let mongoAccontCollection = client.db(process.env.MONGODB).collection(process.env.MONGOCOL);
            mongoAccontCollection.findOne({ email: req.body.email }, (err, account) => {
                client.close();
                if (err) {
                    res.status(501).json({
                        msg: 'mongodb find error',
                        detail: err.message
                    });
                } else {
                    if (account) {
                        res.status(200).json(account});
                    else 
                        res.status(400).json({
                            msg: 'account not found'
                        });
                }
            });
        }
    });
}

Nová async/await implementace

// opet Expressjs funkce s obsluhou routy pro vycitani dat z databaze
const MongoClient = require('mongodb').MongoClient;

async function getUser(req, res) {
    try {
        let client = await MongoClient.connect(process.env.MONGOURL, { useNewUrlParser: true });
        let user = await client
            .db(process.env.MONGODB)
            .collection(process.env.MONGOCOL)
            .findOne();
        client.close();
        if (user) res.status(200).json(user);
        else res.status(400).json({msg: 'account not found'});
    } catch (err) {
        res.status(500).json({
            msg: err.message
        });
    }
}

Resumé

Na první pohled jde vidět několik věcí: ošetření všech chyb se přesouvá jen do jednoho místa a tím odpadá mnoho opakujícího se kódu, výsledek, načtená data nejsou nikde hluboce zanořená a nemusíte řešit problém s kaskádou otevřených závorek if-else větví.
Nutno podotknout, že výhoda nového zápisu ještě více vzroste v momentě, kdy máte sérii callback dotazů a obslužný kód vám začne ještě více narůstat.

Vedle toho si samozřejmě dokáži představit kód, kde bych se dál držel callback zápisu, ale to je věc konkrétního použití.