My class
import * as redis from 'redis';
export class RedisClient {
private client: any
constructor() {
this.client = redis.createClient()
}
public async set(key: string, value: any): Promise<void> {
return new Promise((resolve, reject) => {
this.client.set(key, value, (err: any) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
public async get(key: string): Promise<string> {
return new Promise((resolve, reject) => {
this.client.get(key, (err: any, value: string | PromiseLike<string>) => {
if (err) {
reject(err);
} else {
resolve(value);
}
});
});
}
}
I know I need to add this.client.connect()
and I was hoping I could add it to constructor but that doesn’t work. I get client is closed. It does work if I add this.client.connect
within the set method but is the approach considered good if we are connecting to Redis every single time before calling set/get?
Is there a better approach to this
Update:
Taking answer into suggestion, created with Singleton pattern. Added the following in RedisClient
let cached: Promise<RedisClient>;
static instance(): Promise<RedisClient> {
if (!cached) cached = RedisClient.create();
return cached;
}
In caller class
constructor() {
this.redisClient = RedisClient.instance();
}
public async handle(event: DynamoDBStreamEvent): Promise<void> {
const client = await this.redisClient;
....
}
This works but I am not too familiar with typescript. Is this considered a good pattern. My intention is that RedisClient is only instantiated once so we are not always re-connecting to Redis with every operation
2
Answers
This is just a limitation of JavaScript and thus TypeScript. The
.connect
function isasync
and so you can’t put it in the constructor. What’s happening is that the resolution of the call to.connect
is not happening before the rest of your code runs. You need to wait for.connect
to resolve before you can use the Redis client.If I find myself writing this sort of class, I usually add a static method that calls
.createClient
and.connect
together and then use that method instead ofnew
. There’s a lot of ways to skin this cat, but here’s one:Note a few things here:
client
toconnection
since you are creating a class calledRedisClient
as I thought it would be confusing to have two things called "Client".any
for you usingReturnType
! 😉You might even take this a step further and use a Singleton pattern here as Redis rarely needs more than one connection for a Node.js application.
What i would do in your situation is the wrap the redis connection in a IIF and assign the result to the client property on the class
}