如何在TypeScript中基于node-redis实现ioredis scanStream类似功能?
node-redis(TypeScript)实现ioredis scanStream的等价功能
原ioredis实现代码
const stream = redis.scanStream({ match: "kaboom:moves:*", }); const gameIds: any = []; stream.on('data', (keys: any) => { // 提取gameId并添加到数组 keys.forEach((key: any) => gameIds.push(key.split(':')[2])); }); stream.on('end', () => { res.status(200).json({ data: { gameIds, length: gameIds.length }, status: 'success', }) });
你的node-redis尝试代码(需修正)
const stream = client.scanIterator({ TYPE: "string", // `SCAN` only MATCH: "kaboom:moves:*", COUNT: 100, }); const LIMIT = 3; const asyncIterable = { [Symbol.asyncIterator]() { let i = 0; return { next() { const done = i === LIMIT; const value = done ? undefined : i++; return Promise.resolve({ value, done }); }, return() { // 当消费者提前调用'break'或'return'时触发 return { done: true }; }, }; }, }; (async () => { for await (const keys of stream) { gameIds.push(keys.split(":")[2]); } })(); const gameIds: any = [];
正确的node-redis(TypeScript)实现
node-redis v4+的scanIterator返回异步迭代器,无需手动监听data/end事件,直接用for await...of循环处理即可,循环结束后返回响应给客户端。
修正后的完整代码:
import { RedisClientType } from 'redis'; import { Request, Response } from 'express'; // 假设client是已初始化的Redis客户端实例 export async function getGameIds(req: Request, res: Response, client: RedisClientType) { const gameIds: string[] = []; // 用明确类型替代any const stream = client.scanIterator({ TYPE: "string", MATCH: "kaboom:moves:*", COUNT: 100, }); try { // 遍历异步迭代器,处理每一批keys for await (const keys of stream) { keys.forEach(key => { const parts = key.split(':'); if (parts.length >= 3) { // 增加边界判断避免错误 gameIds.push(parts[2]); } }); } // 扫描完成后返回响应 res.status(200).json({ data: { gameIds, length: gameIds.length }, status: 'success', }); } catch (err) { // 处理Redis操作异常 res.status(500).json({ status: 'error', message: '获取游戏ID失败' }); } }
关键说明
scanIterator本身已实现Symbol.asyncIterator接口,无需自定义异步迭代器for await...of循环结束即代表所有键扫描完成,等价于ioredis中监听end事件的逻辑- 用
string[]替代any,符合TypeScript类型规范 - 增加错误捕获和边界判断,提升代码健壮性
内容的提问来源于stack exchange,提问作者scranley
相关产品推荐
相关产品推荐

