Rxjs: Is there a best way to bindNodeCallback with "this" object? like reds client?

Created on 20 May 2016  路  5Comments  路  Source: ReactiveX/rxjs

I want to use RxJS to finish a toy project, but I find it is not easy to bindNodeCallback with redisClient methods.
Wrote in TypeScript:

import {createClient} from "redis";
import {Observable} from "rxjs/Rx";

interface RedisClientProtocol {
    set(key: string, value: string, callback?: (error: Error, result: string) => void): void;
    // this is a digest from redis.d.ts from definitedType
}
const redisClient: RedisClientProtocol = createClient();

Then a want to use a Rx version of redisClient.set.

const rx_set = Observable.bindNodeCallback(redisClient.set);

rx_set("test-key", "any-content")
    .do(() => console.log("finished"), (error) => console.log(error))
    .subscribe(() => undefined, () => process.exit(), () => process.exit());

This will trigger an error:

TypeError: this.internal_send_command is not a function
    at BoundNodeCallbackObservable.RedisClient.(anonymous function).RedisClient.(anonymous function) [as callbackFunc] (/Users/frogcjn/Files/Projects/Node.ts-Projects/shoutbox/shoutbox/node_modules/redis/lib/commands.js:45:25)
    at BoundNodeCallbackObservable.tryCatcher (/Users/frogcjn/Files/Projects/Node.ts-Projects/shoutbox/shoutbox/node_modules/rxjs/util/tryCatch.js:6:31)
    at BoundNodeCallbackObservable._subscribe (/Users/frogcjn/Files/Projects/Node.ts-Projects/shoutbox/shoutbox/node_modules/rxjs/observable/BoundNodeCallbackObservable.js:111:64)
    at BoundNodeCallbackObservable.Observable.subscribe (/Users/frogcjn/Files/Projects/Node.ts-Projects/shoutbox/shoutbox/node_modules/rxjs/Observable.js:52:62)

This is because bindNodeCallback will call redisClient.set with BoundNodeCallbackObservable class object, instead of redisClient object. But there is no way to change this behavior. Unless you bind thisObject with lambda function:

function withThis(thisObject: any, method: Function): Function {
    return (...args) => {
        return method.apply(thisObject, args);
    };
}

const rx_set = Observable.bindNodeCallback(withThis(redisClient, redisClient.set));

rx_set("test-key", "any-content")
    .do(() => console.log("finished"), (error) => console.log(error))
    .subscribe(() => undefined, () => process.exit(), () => process.exit());

So I think the bindNodeCallback should have a thisObject parameter to decide which object call the node function, like redisClient.set.

Most helpful comment

Shouldn't Observable.bindNodeCallback(redisClient.set.bind(redisClient)) solve this problem?

Also, bind is a _lot_ faster in newer version of Chrome, FF and Node. All of that started last December I think.

All 5 comments

Shouldn't Observable.bindNodeCallback(redisClient.set.bind(redisClient)) solve this problem?

Also, bind is a _lot_ faster in newer version of Chrome, FF and Node. All of that started last December I think.

If you use This-binding syntax with Babel, you can just write Observable.bindNodeCallback(::redisClient.set) which compiles to the .bind operation

I'm new to ES/JS, so I don't know that methods can bind this.
Thanks you all.
@blesh, @jadbox

No problem, @frogcjn, happy coding!

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

benlesh picture benlesh  路  3Comments

cartant picture cartant  路  3Comments

marcusradell picture marcusradell  路  4Comments

LittleFox94 picture LittleFox94  路  3Comments

unao picture unao  路  4Comments