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.
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.
Most helpful comment
Shouldn't
Observable.bindNodeCallback(redisClient.set.bind(redisClient))solve this problem?Also,
bindis a _lot_ faster in newer version of Chrome, FF and Node. All of that started last December I think.