You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 20:57:20