admin管理员组

文章数量:1316974

I have an Express route like this in an node server (file is required):

var redis = require('../modules/redis');

module.exports = function (app) {

var redisClient = redis.init();


app.post('/auth/ticket', cors(), function (req, res) {


    var hashes = ['hash1','hash2', 'hash3'];

    var candidates = [];  // An array to collect valid hashes
    var key;  
    // to check each hash against a RedisDB I use a For Loop
    for (key in hashes) {
        var hash = hashes[key];
        console.log("Hash " + hash + "  will be proofed now:");
       //now I try to collect the valid hashes in the candidates array
       if (redisClient.exists(hash) === 1) candidates.push(hash);
    }
    console.log(JSON.stringify(candidates));
});
};

Now here is the code of my module which shall manage all the redis requests:

exports.init = function () {
Redis = exports.Redis = function () {
    var promiseFactory = require("q").Promise,
        redis = require('promise-redis')(promiseFactory);

    this.client = redis.createClient();
    this.client.on('error', function (err) {
        console.log('redis error – ' + client.host + ':' + client.port + ' – ' + err);
    });

Redis.prototype.exists = function (key) {
    this.client.exists(key, function (err, data) {
       return data === 1 ? true : false;
    });
};

return new Redis();
};

So what I experience is that the module is able to console.log the results properly. If a hash is valid, it returns true and otherwise false. This works as expected. Problem is, that the for-loop continuous the execution without fetching getting the results. I think this is caused by race-conditions.

As you can see, I have started to workout something there with the use of Q and promise-redis in the top of my code:

 var promiseFactory = require("q").Promise,
    redis = require('promise-redis')(promiseFactory);

this.client = redis.createClient();

I like to know, how I make my for-loop (in the Express route) waiting for the results of redisClient.exists(hash) or in other words, to get all valid hashes into my candidates array.

Please help

I have an Express route like this in an node server (file is required):

var redis = require('../modules/redis');

module.exports = function (app) {

var redisClient = redis.init();


app.post('/auth/ticket', cors(), function (req, res) {


    var hashes = ['hash1','hash2', 'hash3'];

    var candidates = [];  // An array to collect valid hashes
    var key;  
    // to check each hash against a RedisDB I use a For Loop
    for (key in hashes) {
        var hash = hashes[key];
        console.log("Hash " + hash + "  will be proofed now:");
       //now I try to collect the valid hashes in the candidates array
       if (redisClient.exists(hash) === 1) candidates.push(hash);
    }
    console.log(JSON.stringify(candidates));
});
};

Now here is the code of my module which shall manage all the redis requests:

exports.init = function () {
Redis = exports.Redis = function () {
    var promiseFactory = require("q").Promise,
        redis = require('promise-redis')(promiseFactory);

    this.client = redis.createClient();
    this.client.on('error', function (err) {
        console.log('redis error – ' + client.host + ':' + client.port + ' – ' + err);
    });

Redis.prototype.exists = function (key) {
    this.client.exists(key, function (err, data) {
       return data === 1 ? true : false;
    });
};

return new Redis();
};

So what I experience is that the module is able to console.log the results properly. If a hash is valid, it returns true and otherwise false. This works as expected. Problem is, that the for-loop continuous the execution without fetching getting the results. I think this is caused by race-conditions.

As you can see, I have started to workout something there with the use of Q and promise-redis in the top of my code:

 var promiseFactory = require("q").Promise,
    redis = require('promise-redis')(promiseFactory);

this.client = redis.createClient();

I like to know, how I make my for-loop (in the Express route) waiting for the results of redisClient.exists(hash) or in other words, to get all valid hashes into my candidates array.

Please help

Share Improve this question edited Jun 5, 2015 at 7:38 Romski 1,9421 gold badge12 silver badges28 bronze badges asked Jun 4, 2015 at 17:34 gwingergwinger 811 gold badge1 silver badge9 bronze badges 3
  • You can use your promise libary's all() function. This will look them all up simultaneously and return the results when they are done. Beware though that this could put a large load on Redis if you have a lot to look up. – Brad Commented Jun 4, 2015 at 17:55
  • this is a in my case, too. I need to lookup between 1 and 12 hashes averagely. And it is a load balanced system. But I don't know how to implement it correctly. I never used promise it in this circumstances. – gwinger Commented Jun 4, 2015 at 18:10
  • Maybe you could give me code example how you would workout the case. Just a step in, so I can develop it out. – gwinger Commented Jun 4, 2015 at 18:14
Add a ment  | 

3 Answers 3

Reset to default 1

like @brad said, you could use Q.all, it would take an array of promises as input and then return an array of results when all the promises are finished:

there is a mistake in your answer:

Redis.prototype.exists = function (key) {

return this.client.exists(key)      // CHANGED, you still need to return a promise.
    .then(function (reply) {
        console.log("reply " + reply);
        return (reply);
    })
    .catch(console.log);

};

If I understand correctly, what you want is something like

exports.init = function () {
Redis = exports.Redis = function () {
    var Q = require("q"),
        promiseFactory = Q.Promise,
        redis = require('promise-redis')(promiseFactory);

    this.client = redis.createClient();
    this.client.on('error', function (err) {
        console.log('redis error – ' + client.host + ':' + client.port + ' – ' + err);
    });

Redis.prototype.exists = function (key) {
    return this.client.exists(key).then(function (data) {
       return data === 1 ? true : false;
    });
};

Redis.prototype.getActive = function (arry) {
    var self = this;
    return  Q.all(arry.map(self.exists.bind(self))
            ).then(function(res){
                return arry.filter(function(val, idx){ return res[idx];});
            });
};



return new Redis();
};

@ mido22: But did you also recognize that I outsourced all the reds functions to the module file (1st Codeblock) which requires the promise-redid and builds a factory for Q. I changed the code inside the module file to:

    Redis.prototype.exists = function (key) {

    this.client.exists(key)
        .then(function (reply) {
            console.log("reply " + reply);
            return (reply);
        })
        .catch(console.log);

    };

and this results correctly like the console.log evidently shows. Your codechange of the for-loop works very well but I think it don't fulfills my needs perfectly. If I could, I would like to have it pletely outsourced in to the module file, so that I can use the prototyped method in similar cases from everywhere. Is that possible anyhow? I see, that it would result in having two promise supported functionalities, if I would create an Instance of Redis Client with promise-redid and Q inside the auth/ticket/ router, too. like this:

var Q = require('q'),
promiseFactory = Q.Promise,
redis = require("promise-redis")(promiseFactory),
client;

an then the express route (there are a lot of more routes each in a single file) like in your code.

Do you understand what I mean? Of course your solution will be fine for my needs at all, but a module resolving the job pletely could have more elegance if possible so far.

Using with redis, bluebird and typescript:

import { RedisClient, createClient, ClientOpts } from "redis";
import { promisifyAll, PromisifyAllOptions } from "bluebird";


export module FMC_Redis {

    export class Redis {
        opt: ClientOpts;
        private rc: RedisClient;
        private rcPromise: any;

        private static _instance: Redis = null;
        public static current(_opt?: ClientOpts): Redis {

            if (!Redis._instance) {
                Redis._instance = new Redis(_opt);
                Redis._instance.redisConnect();
            }
            return Redis._instance;
        }

        public get client(): RedisClient {
            if (!this.rc.connected) throw new Error("There is no connection to Redis DB!");
            return this.rc;
        }

        /******* BLUEBIRD ********/
        public get clientAsync(): any {
            // promisifyAll functions of redisClient 
            // creating new redis client object which contains xxxAsync(..) functions.
            return this.rcPromise = promisifyAll(this.client);
        }

        private constructor(_opt?: ClientOpts) {
            if (Redis._instance) return;

            this.opt = _opt
                ? _opt
                : {
                    host: "127.0.0.1",
                    port: 6379,
                    db: "0"
                };
        }

        public redisConnect(): void {
            this.rc = createClient(this.opt);
            this.rc
                .on("ready", this.onReady)
                .on("end", this.onEnd)
                .on("error", this.onError);
        }

        private onReady(): void { console.log("Redis connection was successfully established." + arguments); }
        private onEnd(): void { console.warn("Redis connection was closed."); }
        private onError(err: any): void { console.error("There is an error: " + err); }


        /****** PROMISE *********/
        // promise redis test
        public getRegularPromise() {
            let rc = this.client;
            return new Promise(function (res, rej) {
                console.warn("> getKeyPromise() ::");
                rc.get("cem", function (err, val) {
                    console.log("DB Response OK.");
                    // if DB generated error:
                    if (err) rej(err);
                    // DB generated result:
                    else res(val);
                });
            });
        }


        /******* ASYNC - AWAIT *******/
        // async - await test function
        public delay(ms) {
            return new Promise<string>((fnResolve, fnReject) => {
                setTimeout(fnResolve("> delay(" + ms + ") > successfull result"), ms);
            });
        }

        public async delayTest() {
            console.log("\n****** delayTest ")
            let a = this.delay(500).then(a => console.log("\t" + a));

            let b = await this.delay(400);
            console.log("\tb::: " + b);
        }

        // async - await function
        public async getKey(key: string) {
            let reply = await this.clientAsync.getAsync("cem");
            return reply.toString();
        }
    }
}

let a = FMC_Redis.Redis.current();
// setTimeout(function () {
//     console.warn(a.client.set("cem", "naber"));
//     console.warn(a.client.get("cem"));
//     console.warn(a.client.keys("cem"));
// }, 1000);

/***** async await test client *****/
a.delayTest();


/** Standart Redis Client test client */
setTimeout(function () {
    a.client.get("cem", function (err, val) {
        console.log("\n****** Standart Redis Client")
        if (err) console.error("\tError: " + err);
        else console.log("\tValue ::" + val);
    });
}, 100)

/***** Using regular Promise with Redis Client > test client *****/
setTimeout(function () {
    a.getRegularPromise().then(function (v) {
        console.log("\n***** Regular Promise with Redis Client")
        console.log("\t> Then ::" + v);
    }).catch(function (e) {
        console.error("\t> Catch ::" + e);
    });
}, 100);

/***** Using bluebird promisify with Redis Client > test client *****/
setTimeout(function () {
    var header = "\n***** bluebird promisify with Redis Client";
    a.clientAsync.getAsync("cem").then(result => console.log(header + result)).catch(console.error);
}, 100);

本文标签: javascriptnodejs redis and how to use promise when using a moduleStack Overflow