8

I am trying to get few values from redis, combine them and eventually send. But I just can't make those promises work.

This is the simple get functions from redis

client.get('user:1:id',function(err,data){
    // here I have data which contains user ID
});
client.get('user:1:username',function(err,data){
    // here I have data which contains username
});

Now I want to get ID and username and send them, but I have no idea how to make that work. I manage to make it work with callbacks but it is very messy result, so then i tried to wrap anonymous functions into Q.fcall and after call .then which looks something like that

client.get('user:1:id',Q.fcall(function(err,data){
    return data;
}).then(function(val) {
   // do something
}));

but that gives me error for too many arguments been passed and I'm not even sure if that would help me even if it would work.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Giedrius
  • 1,590
  • 3
  • 16
  • 27

3 Answers3

10
Q.all([Q.ninvoke(client, 'get', 'user:1:id'),
       Q.ninvoke(client, 'get', 'user:1:username')]).then(function (data) {
  var id = data[0];
  var username = data[1];
  // do something with them
});

See https://github.com/kriskowal/q#adapting-node

Dan D.
  • 73,243
  • 15
  • 104
  • 123
  • that seems to be a nice approach, and works well, though I'm still missing the part how can I combine id and username in one object for sending to browser without making things too messy. Could you share some knowledge here please. – Giedrius Nov 15 '12 at 01:39
  • Thank you very much, now these promises starts to make a bit more sense for me. – Giedrius Nov 15 '12 at 01:52
  • 4
    You can squeeze more out using Q.spread. Q.spread([Q.ninvoke(client, "get", "user:1:id"), Q.ninvoke(client, "get", "user:1:username"], function (id, username) {}). – Kris Kowal Jan 28 '13 at 03:14
  • I wish I could upvote you more than once. I used this to answer my own Stack Overflow question: http://stackoverflow.com/questions/34902092/express-node-js-receiving-redis-callback-executing-promises – Les Paul Jan 23 '16 at 02:05
0

I use a simple RequireJS module using node-redis and whenjs to create a lifted redis wrapper:

define [
  'redis/lib/commands'
  'when'
  'when/node/function'
], (Commands, When, NodeFn) ->
  'use strict'

  lift = (redis) ->
    wrapped = {}
    Commands.map (cmd) ->
      wrapped[cmd] = (args...) ->
        def = When.defer()
        args.push NodeFn.createCallback def.resolver
        redis[cmd].apply redis, args
        def.promise
    wrapped

  {lift}

Usage is straightforward:

client = lift redis.createClient()
client.get("hello").then console.log, console.error
0

Using Promise, Bluebird and node_redis:

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);

enter image description here

uzay95
  • 16,052
  • 31
  • 116
  • 182