简体   繁体   English

Node.js 中的“异步”/“等待”在 Node.js v8.1.0 中不起作用

[英]'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.我正在尝试刷新 Redis 缓存数据库并在响应中返回状态。 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.在下面的代码中, console.log()调用将始终打印 undefined,因为没有等待 flushRedisDB。

My Node.js version is v8.1.0我的 Node.js 版本是 v8.1.0

File myfile.js文件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文件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?我该如何解决这个问题?

Async/await only works with promises (as said in the comment).异步/等待仅适用于承诺(如评论中所述)。 So just wrap your callback into a Promise.所以只需将回调包装到 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) .仅当回调的签名为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.所以在这种情况下,只需去除 err 参数、拒绝和 try/catch 处理程序。

I let my answer in place here for convenience because it will most probably help you solve it for other Redis related methods.为了方便起见,我在这里给出了答案,因为它很可能会帮助您解决其他与 Redis 相关的方法。

async/await only works with promises so this code doesn't wait for a callback async/await仅适用于 promises,因此此代码不会等待回调

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

You need to promisify the flushall method.您需要承诺flushall方法。 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. Node.js 版本 8 和更高版本中内置了util.promisify函数,它允许 promisify Node.js 样式的CPS函数。 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 .关于util.promisify

Bluebird offers its own promisification which will promisify all Redis functions allowing you to just append Async to any Redis command you wish to use. Bluebird提供了自己的 promisification,它将promisify 所有 Redis 功能,允许您将Async附加到您希望使用的任何 Redis 命令。 In your case, it would look like flushallAsync .在您的情况下,它看起来像flushallAsync

const redis = require('redis');
const bluebird = require('bluebird');

bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);

Once promisified you can use async / await to your heart's content.一旦得到承诺,您就可以随心所欲地使用 async / await 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM