javascriptnode.jsexpressasynchronousmorgan

How to return properly using async in this code


So i have this code

const log = require("./queries/logQuery");
const moment = require('moment');
const morgan = require('morgan');

const custom = async (tokens, req, res) => {
    if(req.session){
        if(req.session.superadmin){
            const date = moment().locale('id').format('DD-MM-YYYY HH:mm:ss');
            const usr = req.session.superadmin;
            const method = tokens.method(req, res);
            const endpoint = tokens.url(req, res);
            const statusCode = tokens.status(req, res);

            await log.addLog(date, usr, method, endpoint, statusCode)
        }else if(req.session.user){
            const date = moment().locale('id').format('DD-MM-YYYY HH:mm:ss');
            const usr = req.session.user;
            const method = tokens.method(req, res);
            const endpoint = tokens.url(req, res);
            const statusCode = tokens.status(req, res);
    
            await log.addLog(date, usr, method, endpoint, statusCode)
        }
        return [
            tokens.method(req, res),
            tokens.url(req, res),
            tokens.status(req, res),
            tokens.res(req, res, 'content-length'), '-',
            tokens['response-time'](req, res), 'ms'
        ].join(' ')
    }
}

router.use(morgan(custom))

I'm trying to use async in the morgan logger, however the return always gave me "[object Promise]", i've tried setting each of the return using await but to no avail, how to fix this?


Solution

  • This is a confusing question. custom is an async function thus is ALWAYS returns a promise. That's how ALL async functions work.

    But, it looks like morgan wants the callback you pass it to synchronously return that array. You can't do what you're trying to do the way you're trying to do it as the morgan API does not support using an async callback.

    One way to solve this problem would be to remove the await on await log.addLog(...) so you can then remove the async on the custom function:

    const custom = (tokens, req, res) => {
        if(req.session){
            if(req.session.superadmin){
                const date = moment().locale('id').format('DD-MM-YYYY HH:mm:ss');
                const usr = req.session.superadmin;
                const method = tokens.method(req, res);
                const endpoint = tokens.url(req, res);
                const statusCode = tokens.status(req, res);
    
                log.addLog(date, usr, method, endpoint, statusCode).catch(err => console.error);
            }else if(req.session.user){
                const date = moment().locale('id').format('DD-MM-YYYY HH:mm:ss');
                const usr = req.session.user;
                const method = tokens.method(req, res);
                const endpoint = tokens.url(req, res);
                const statusCode = tokens.status(req, res);
        
                log.addLog(date, usr, method, endpoint, statusCode).catch(err => console.error);
            }
            return [
                tokens.method(req, res),
                tokens.url(req, res),
                tokens.status(req, res),
                tokens.res(req, res, 'content-length'), '-',
                tokens['response-time'](req, res), 'ms'
            ].join(' ')
        }
    }