nodejs redis Q promises, как заставить его работать?

Я пытаюсь получить несколько значений от Redis, объединить их и в конечном итоге отправить. Но я просто не могу заставить эти обещания работать.

Это простые функции get из 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
});

Теперь я хочу получить ID и username и отправить их, но понятия не имею, как это сделать. Мне удалось заставить его работать с обратными вызовами, но это очень беспорядочный результат, поэтому я попытался обернуть анонимные функции в Q.fcall и после вызова .then, что выглядит примерно так

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

но это дает мне ошибку из-за того, что было передано слишком много аргументов, и я даже не уверен, поможет ли это мне, даже если это сработает.


person Giedrius    schedule 15.11.2012    source источник


Ответы (3)


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

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

person Dan D.    schedule 15.11.2012
comment
это кажется хорошим подходом и хорошо работает, хотя мне все еще не хватает той части, как я могу объединить идентификатор и имя пользователя в один объект для отправки в браузер, не делая вещи слишком грязными. Не могли бы вы поделиться некоторыми знаниями здесь, пожалуйста. - person Giedrius; 15.11.2012
comment
Большое спасибо, теперь эти обещания начинают иметь для меня немного больше смысла. - person Giedrius; 15.11.2012
comment
Вы можете выжать больше, используя Q.spread. Q.spread([Q.ninvoke(клиент, получить, пользователь:1:идентификатор), Q.ninvoke(клиент, получить, пользователь:1:имя пользователя], функция (идентификатор, имя пользователя) {}). - person Kris Kowal; 28.01.2013
comment
Я хотел бы проголосовать за вас более одного раза. Я использовал это, чтобы ответить на свой собственный вопрос о переполнении стека: получение обратного вызова redis, выполнение обещаний"> stackoverflow.com/questions/34902092/ - person Les Paul; 23.01.2016

Я использую простой модуль RequireJS, используя node-redis и whenjs, чтобы создать поднятую оболочку Redis:

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}

Использование простое:

client = lift redis.createClient()
client.get("hello").then console.log, console.error
person Jeremie Pelletier    schedule 03.10.2013

Используя Promise, Bluebird и 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);

введите здесь описание изображения

person uzay95    schedule 25.04.2017