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

JS中TimeLimitedCache的setTimeout使用问题排查请求

TimeLimitedCache缓存类的问题分析

最近练习JavaScript数据结构与算法,实现了一个支持键值自动过期的TimeLimitedCache缓存类,但实际运行输出与预期不符。以下是实现代码及测试逻辑:

function TimeLimitedCache(){
    this.cache = {};
    
    this.set = function (key, value, duration) {
        let timer;
        let result = false;
        if(key in this.cache){
            clearTimeout(timer);
            result = true;
        }
        this.cache[key] = value;
        timer = setTimeout(()=> delete this.cache[key],duration);
        return result;
    }

    this.get = function(key){
        return this.cache[key] ? this.cache[key] : -1;
    }

    this.count = function(){
        return Object.keys(this.cache).length;
    }
    
}

const start = new Date().getSeconds();
const tesr = new TimeLimitedCache();

setTimeout(()=>console.log(tesr.set(1,42,50)),start)
setTimeout(()=>console.log(tesr.set(1,50,100)),start+40)
setTimeout(()=>console.log(tesr.get(1)),start+50)
setTimeout(()=>console.log(tesr.get(1)),start+120)
setTimeout(()=>console.log(tesr.get(1)),start+200)
setTimeout(()=>console.log(tesr.count(1)),start+250)

问题原因分析

  • 定时器清除逻辑失效:set方法中的timer是局部变量,每次调用set都会创建新的变量实例。当更新同一个key时,clearTimeout(timer)清除的是刚声明的空timer(值为undefined),完全无法触达之前为该key设置的定时器。旧定时器仍会在到期后删除缓存,导致后续读取结果不符合预期。
  • 缓存结构设计缺陷:当前cache对象仅存储键值对,未保存对应key的定时器ID,无法在更新key时定位并清除旧定时器。
  • 测试时间单位错误:new Date().getSeconds()获取的是当前时间的秒数(0-59),但setTimeout的第二个参数要求是毫秒数。这会导致测试的时间触发逻辑完全混乱,比如原本想设置30秒后执行,实际变成30毫秒后执行。
  • count方法调用冗余:测试代码中调用tesr.count(1),但count方法定义时不需要参数,不过这只会传递无用参数,不影响核心功能。

修复方案

1. 调整缓存存储结构

修改cache,让每个key对应的值包含实际数据和定时器ID:

function TimeLimitedCache(){
    this.cache = {};
    
    this.set = function (key, value, duration) {
        let result = false;
        // 存在旧缓存则清除对应定时器
        if(key in this.cache){
            clearTimeout(this.cache[key].timer);
            result = true;
        }
        // 存储值与定时器ID
        this.cache[key] = {
            value: value,
            timer: setTimeout(() => delete this.cache[key], duration)
        };
        return result;
    }

    this.get = function(key){
        return this.cache[key] ? this.cache[key].value : -1;
    }

    this.count = function(){
        return Object.keys(this.cache).length;
    }
}

2. 修正测试时间逻辑

把秒数改为毫秒级时间戳,确保测试时序符合预期:

const start = new Date().getTime();
const tesr = new TimeLimitedCache();

setTimeout(()=>console.log(tesr.set(1,42,50)), start);
setTimeout(()=>console.log(tesr.set(1,50,100)), start + 40);
setTimeout(()=>console.log(tesr.get(1)), start + 50);
setTimeout(()=>console.log(tesr.get(1)), start + 120);
setTimeout(()=>console.log(tesr.get(1)), start + 200);
setTimeout(()=>console.log(tesr.count()), start + 250);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 08:15:06