如何在JavaScript中缓存非连续移位范围的数据?

时间:2011-05-09 14:08:41

标签: javascript algorithm caching

编辑:为简单起见,为了尝试使这个问题和示例代码更通用,我省略了一个细节。根据其中一个反应(很棒)的细节证明是重要的。该系统主要用于显示日期范围内的事物。代码中的低/高数字通常表示Unix时间戳,其范围可能跨越数周或数月。 结束修改

我有一个页面,其中提供了具有属于特定范围的属性的数据对象的视图。当用户与视图交互以更改它时,它通常是对范围的顺序更改(0-9,10-19 ...)。我正在从服务器检索这些数据,当它进入时,我将其缓存,以便随后对该范围内的数据的请求已经可用。在每次读取数据时,我首先检查是否有缓存数据,如果不是,我从服务器读取并调整缓存。

这里有一个粗略的,过于简化的例子:

var cache, haveCache, read;

cache = {
    rangeLow: 0,
    rangeHigh: 10,
    data: [
        //whatever has been read so far between current low and high
        {
            low: 1,
            high: 3,
            // ...other props
        },
        {
            low: 5,
            high: 6,
            // ...other props
        },
        //...
    ]
};

haveCache = function( low, high )
{
    return ! ( low < cache.rangeLow || high > cache.rangeHigh );
};

read = function( low, high )
{
    var data;

    if( ! haveCache( low, high ) )
    {
        //go to outside source and read in info , then merge to cache
        //
        // when merging to cache:
        //    if `low` param is lower than `cache.rangeLow`, overwrite cache.rangeLow with `low`
        //    if `high` param is higher than `cache.rangeHigh`, overwrite `cache.rangeHigh` with `high`
    }

    //read data from cache

    return data;
};

只要范围的变化确实是连续的,这就很有用。但是,我意识到有一种方法可以非顺序地更改视图并跳过一大组值。因此,假设我正在显示范围10-19,并且我有一个缓存保持0-29范围。然后,用户要求查看范围为60-69的数据。它目前的工作方式,我会要求服务器提供数据,然后将其恢复并呈现。但现在缓存范围低和范围高从0-69运行,而它实际上只保存0-29和60-69范围内的数据。属性范围为30-59的项目不在缓存中,永远不会被检索。

我可以使用什么(更好,更有效)的机制或算法来存储缓存信息并确定我当前显示的范围是否在缓存中?

非常感谢, 吉姆

3 个答案:

答案 0 :(得分:2)

您似乎拥有数据的“块”,每个数据包含10个对象。计算您可以在缓存中存储的这些块的数量,让我们调用此cache_size。现在,您可以使用缓存中的块列表,例如。 cache_size 4:

20-29
0-9
40-49
30-39

这种维护此列表以及检查某个对象是否在缓存中的方式会有点复杂,但我认为这是值得的。

您可能还考虑为每个块保留一个时间或日期索引,以确定最后一次检索到它的对象的时间,这样当您的缓存已满并且您将不得不丢弃缓存的块时,您可以放弃最古老的。

答案 1 :(得分:2)

我认为你应该改变你的hasCache以获得更多flatten key =&gt;值。

例如,可以改为:

1..4
5..7
10..14

只需:

1,1,1,1,   // means like 1=>true,    2=>true,   3=>true,   4=>true
1,1,1,     // means like 5=>true,    6=>true,   7=>true
0,0,       // means like 8=>false,   9=>false
1,1,1,1,1  // means like 10=>false, 11=>false, 12=>false, 13=>false, 13=>false

然后你只需更改你的hasCache函数来确定你是否在任何范围内都有缓存。 在缓存更新时,您还需要通过填充/添加所需的值1来更新新的缓存索引。

对于时间戳案例

你应该在另一种观点中展平:

var cache = {
    1304960585 : {/* your data for 1304960585 */},
    1304960586 : {/* your data for 1304960586 */},
    1304960999 : {/* your data for 1304960999 */},
};
// then in haveCache function you should have something like:
function haveCache(start, end) {
    for (var i = start; i <= end; i++) {
        if (undefined == cache[i]) {
            return false;
        }
    }
    return true;
}

对于缓存中部分范围而非部分范围内的情况 - 您应该为自己创建。

答案 2 :(得分:1)

我要改变那些

haveCache = function( low, high )
{
    if( low < cache.rangeLow || high > cache.rangeHigh )return undefined;
    for(var i = 0;i<cashe.data.length;i++){
        if( !(low < cache.data[i].low || high > cache.data[i].high) )
             return cache.data[i]
    }
    return undefined;
};

这也会返回cashe中的数据元素,因此您无需再次搜索

var data;
if((data=haveCashe(low,high))==undefined){
    //read from server and store in cashe
}
return data;