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

Node.js与Redis Web应用异步Get方法疑问:是否需将函数放入回调?

问题解答

肯定要把get_recent_tweet的调用(包括启动定时任务的setInterval)放进redisClient.get()的回调里,原因很直白:

redisClient.get()是异步操作,它的回调要等Redis把数据返回后才会执行。要是你在回调外面直接开定时任务跑get_recent_tweet,那counts变量大概率还没拿到Redis里存的历史统计值,还是初始的0,这就会导致后续统计直接从0开始算,把之前存在Redis里的历史数据给覆盖掉,统计结果肯定错。

比如你原代码里,setInterval可能在Redis还没把tweet_counts读回来的时候就已经开始跑了,这时候counts还是0,完全没用到Redis里的正确初始值,等于白存了之前的统计。

调整后的代码示例

改完之后的代码大概是这样,确保先从Redis拿到初始计数,再启动定时任务:

const twitterClient = require('./init')
let counts = 0;
const tweet_array_IDs = [];
const hashtag_search = "covid";
const pattern = "vaccine";
const redis = require("redis");

const redisClient = redis.createClient({
    legacyMode: true,
});

// 先连接Redis,成功后再处理初始化
redisClient.connect().then(() => {
    redisClient.get(pattern, function (err, tweet_counts) {
        if (err) {
            console.log("Redis读取错误: " + err);
            counts = 0; // 出错就从0开始
        } else {
            // 有数据就转成数字,没有就设为0
            counts = tweet_counts ? parseInt(tweet_counts, 10) : 0;
        }

        // 一切准备就绪,启动定时任务
        setInterval(() => {
            get_recent_tweet(hashtag_search, pattern);
        }, 3000);
    });
}).catch(err => console.error('Redis连接失败:', err));

function get_recent_tweet(hashtag_search, pattern) {
    twitterClient.tweets.search({
        q: '#' + hashtag_search,
        result_type: 'recent',
    }).then((response) => {
        const tweet_array = response.statuses;
        tweet_array.forEach(tweet => {
            // 用includes代替indexOf,更直观
            if (!tweet_array_IDs.includes(tweet.id)) {
                tweet_array_IDs.push(tweet.id);
                if (tweet.text.includes(pattern)) {
                    counts++;
                    redisClient.incr(pattern);
                }
            }
        });
    }).catch(err => console.error('推文搜索出错:', err));
}

// 别在定时任务里导出,直接导出一个获取计数的方法,外部才能拿到最新值
module.exports = {
    getCurrentCount: () => counts
};

额外提几个要注意的坑

  • tweet_array_IDs存在内存里,重启应用就没了,之前处理过的推文ID会丢失,导致重复统计老推文。建议把这些ID存到Redis的集合里,用SADD添加、SISMEMBER判断是否已处理,这样重启后也不会丢。
  • 原代码里把module.exports = counts放在setInterval里完全没用,模块导出是一次性的,只会导出最开始的0值。要让外部能拿到最新计数,就得像上面那样导出一个函数。
  • 要是觉得回调写法麻烦,可以关掉legacyMode,用Redis的Promise API,配合async/await写代码,可读性会好很多。

内容的提问来源于stack exchange,提问作者S214ky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 00:56:30