Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'async'/'await' in Node.js is not working in Node.js v8.1.0

I am trying to flush the Redis cache database and return the status in the response. But before the cache is cleared it returns the response.

In the below code the console.log() call will always print undefined since flushRedisDB is not awaited.

My Node.js version is v8.1.0

File myfile.js

async function flushRedisapi(request, response)
{
    try {
        var value = await redisModules.flushRedisDB();
        console.log("the value is: " + value);
        if(value)
            response.status(200).send({status : 'Redis Cache Cleared'});
        else
            response.status(400).send({status : "Redis Cache could not be flushed"});

    } catch (error) {
        response.status(400).send({status : "Redis Cache could not be flushed"});
    }
}

File redismodule.js

var redisClient;        // Global (avoids duplicate connections)

module.exports =
{
    openRedisConnection : function()
    {
        if (redisClient == null)
        {
            redisClient = require("redis").createClient(6379, 'localhost');
            redisClient.selected_db = 1;
        }
    },
    isRedisConnectionOpened : function()
    {
        if (redisClient && redisClient.connected == true)
        {
            return true;
        }
        else
        {
            if(redisClient)
                redisClient.end();  // End and open once more

            module.exports.openRedisConnection();

            return true;
        }
    },
    flushRedisDB: async function()
    {
        if(!module.exports.isRedisConnectionOpened())
            return false;

        await redisClient.flushall(function (err, result)
        {
            return (result == 'OK') ? true : false;
        });
    }
};

How can I solve this issue?

like image 583
Sharath Avatar asked Dec 06 '22 14:12

Sharath


2 Answers

Async/await only works with promises (as said in the comment). So just wrap your callback into a Promise.

function cbToPromise(asyncFunc, ...params) {
    return new Promise((resolve, reject) => {
        asyncFunc(...params, (err, result) => {
            if (err) reject(err);
            else resolve(result);
        });
    });
};

try {
    const result = await cbToPromise(redisClient.flushall);
    return result == 'OK';
}
catch(err) {
    console.error(err);
} 

Addendum:

It will work only if the signature of the callback is function(err, result). Which, according to the other answer, would not be the case (no error passed as first parameter), as it never fail. So in this case just strip the err parameter, reject, and try/catch handler.

I let my answer in place here for convenience because it will most probably help you solve it for other Redis related methods.

like image 118
FitzFish Avatar answered Dec 08 '22 03:12

FitzFish


async/await only works with promises so this code doesn't wait for a callback

await redisClient.flushall(function (err, result)
{
    return (result == 'OK') ? true : false;
});

You need to promisify the flushall method. According to the documentation it always succeed.

const flushall = () => new Promise(resolve => redisClient.flushall(resolve))

const flushed = await flusall()

BTW. There is util.promisify function built-in in Node.js version 8 and later that allows to promisify Node.js style CPS functions. But it won't handle always succeeding function like this, so you'd need to provide a custom implementation for it to work. About util.promisify.

like image 30
Yury Tarabanko Avatar answered Dec 08 '22 04:12

Yury Tarabanko