# cache2

> 一个简单的 JavaScript 缓存管理，支持浏览器端和 node 端。

Latest version **3.1.6** (published 2026-03-02) · MIT license · 1.5K weekly downloads

## Install

```sh
npm install cache2
pnpm add cache2
yarn add cache2
bun add cache2
```

## Health

**Score 70/100 (B)** — status: stable.

Positive: has types; esm support; no vulnerabilities; high quality score.

## Facts

| | |
|---|---|
| Version | 3.1.6 |
| Published | 2026-03-02 |
| First published | 2023-01-09 |
| Weekly downloads | 1.5K |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 2 |
| Unpacked size | 206.3 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | caijf |
| Maintainers | caijf |
| Keywords | cache, node, browser, store, storage, memory, ttl |

## Links

- npm: https://www.npmjs.com/package/cache2
- Repository: https://github.com/caijf/cache2
- Homepage: https://github.com/caijf/cache2#readme
- Issues: https://github.com/caijf/cache2/issues
- npm.io page: https://npm.io/package/cache2

## Dependencies (2)

- [tslib](https://npm.io/package/tslib.md) ^2.8.1
- [emitter-pro](https://npm.io/package/emitter-pro.md) ^1.2.4

## Alternatives

- [memory-cache](https://npm.io/package/memory-cache.md) — 795.0K weekly downloads
- [@httptoolkit/proxy-agent](https://npm.io/package/@httptoolkit/proxy-agent.md) — 11.2K weekly downloads
- [express-cache-controller](https://npm.io/package/express-cache-controller.md) — 5.3K weekly downloads
- [http-cache-middleware](https://npm.io/package/http-cache-middleware.md) — 4.5K weekly downloads
- [@magnetarjs/plugin-vue3](https://npm.io/package/@magnetarjs/plugin-vue3.md) — 790 weekly downloads

## Recent versions

- 3.1.6 (latest) — 2026-03-02
- 2.0.7 (latest-2) — 2024-10-22
- 3.1.5 — 2026-02-11
- 3.1.4 — 2026-01-28
- 3.1.3 — 2026-01-15
- 3.1.2 — 2024-11-19
- 3.1.1 — 2024-10-15
- 3.1.0 — 2024-09-09
- 3.0.1 — 2024-09-02
- 3.0.0 — 2024-06-17
- 2.0.6 — 2024-06-17
- 2.0.5 — 2024-05-14
- 2.0.4 — 2024-05-13
- 2.0.3 — 2024-03-19
- 2.0.2 — 2024-03-13
- … 20 more at https://npm.io/package/cache2/versions

## README

# Cache2

[![npm][npm]][npm-url] [![codecov](https://codecov.io/gh/caijf/cache2/graph/badge.svg?token=00EFPCEHYH)](https://codecov.io/gh/caijf/cache2) ![npm](https://img.shields.io/npm/dt/cache2) ![GitHub](https://img.shields.io/github/license/caijf/cache2.svg)

一个简单的 JavaScript 缓存管理，支持浏览器端和 node 端。

主要包含 2 个类：

- [Storage](#storage) - 基本的数据存储管理，支持 `自定义缓存`。
- [Cache](#cache) - 功能丰富的数据存储管理，支持 `自定义缓存` `命名空间` `数据过期时间` `限制缓存数量` `自定义事件`。

## 快速入门

### 安装

#### es/cjs

```shell
npm install cache2
```

```shell
yarn add cache2
```

```shell
pnpm add cache2
```

#### umd

如果你的项目使用的是原生方式开发，可以在浏览器中使用 `script` 标签直接引入文件，并使用全局变量 `cache2`。

`npm` 包的 [cache2/dist](https://www.npmjs.com/package/cache2?activeTab=code) 目录下提供了 `UMD` 包 `cache2.js` 以及 `cache2.min.js`。你也可以直接使用`cdn`：

- jsdelivr: <https://cdn.jsdelivr.net/npm/cache2@3>
- unpkg: <https://unpkg.com/cache2@3>

### 示例

#### 1.浏览器存储

[Storage](#storage) 自定义缓存后，存取数据时自动处理序列化和解析数据。

```typescript
import { Storage } from 'cache2';

const local = new Storage(window.localStorage);

local.set('foo', { a: 1, b: ['bar'], c: ['x', 2, 3] });
local.get('foo');
// { a: 1, b: ['bar'], c: ['x', 2, 3] }

local.del('foo');
local.get('foo');
// null
```

#### 2.过期时间、限制数量

[Cache](#cache) 默认命名空间名称 `'default'`，使用内存缓存。

```typescript
import { Cache } from 'cache2';

const myCache = new Cache({
  stdTTL: 60 * 1000
  max: 20
});

myCache.set('foo', { baz: 42 });
myCache.get('foo');
// { baz: 42 }

// 60 seconds later ...

myCache.get('foo');
// undefined
```

#### 3.命名空间、自定义缓存、过期时间

[Cache](#cache) 自定义缓存后，存取数据时自动处理序列化和解析数据。

```typescript
import { Cache } from 'cache2';

const myCache = new Cache('namespace', {
  storage: localStorage,
  stdTTL: 60 * 1000
});

myCache.set('foo', { baz: 42 }, 10 * 1000);
myCache.set('bar', 'abc');

myCache.get('foo');
// { baz: 42 }

myCache.get('bar');
// 'abc'

// 10 seconds later ...

myCache.get('foo');
// undefined

myCache.get('bar');
// 'abc'

// 60 seconds later ...

myCache.get('bar');
// undefined
```

## Storage

数据存储管理。适用于简单的内存缓存、浏览器存储。

```typescript
import { Storage, StorageOptions } from 'cache2';

declare class Storage<ValueType = any> {
  constructor(storage?: TStorage, options?: Partial<StorageOptions>);
}

const memory = new Storage();
const memory2 = new Storage(undefined, options);
const local = new Storage(window.localStorage, options);
const session = new Storage(window.sessionStorage, options);
```

### StorageOptions

| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| needParsed | 存取数据时是否需要序列化和解析数据。<br/>如果使用内置的内存缓存，默认 `false`，如果自定义 `storage` 默认 `true`。 | `boolean` | - |
| replacer | 数据存储时序列化的参数，透传给 [JSON.stringify](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) 的 `replacer` 参数。<br/>仅在 `needParsed=true` 时生效。 | `(key: string, value: any) => any` | - |
| reviver | 数据获取时转换的参数，透传给 [JSON.parse](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) 的 `reviver` 参数。<br/>仅在 `needParsed=true` 时生效。 | `(key: string, value: any) => any` | - |
| prefix | 缓存键前缀。便于管理同域名下的不同项目缓存。 | `string` | - |

### Storage 实例方法

#### storage.get(key: string)

获取存储的数据。如果键值存在返回键值，否则返回 `null`。

```typescript
const local = new Storage(window.localStorage);
local.set('foo', { baz: 42 });
local.get('foo');
// { baz: 42 }
```

#### storage.set(key: string, data: ValueType)

存储数据。

```typescript
const local = new Storage(window.localStorage);
local.set('foo', { baz: 42 });
local.get('foo');
// { baz: 42 }
```

#### storage.del(key: string)

删除存储的数据。

```typescript
const local = new Storage(window.localStorage);
local.set('foo', { baz: 42 });
local.get('foo');
// { baz: 42 }

local.del('foo');
local.get('foo');
// null
```

#### storage.clear()

清除存储的所有键。

_⚠️注意：该方法调用 `storage.clear()`，可能会将同域下的不同实例的所有键都清除。如果要避免这种情况，建议使用 [Cache](#cache)。_

```typescript
const local = new Storage(window.localStorage);
local.set('foo', { baz: 42 });
local.get('foo');
// { baz: 42 }

local.clear();
local.get('foo');
// null
```

## Cache

功能丰富的数据存储管理，支持 `自定义缓存` `命名空间` `数据过期时间` `限制缓存数量` `自定义事件`。

```typescript
import { Cache, CacheOptions } from 'cache2';

declare class Cache<ValueType = any> extends Emitter<(key: string, value: ValueType) => void> {
  constructor(options?: Partial<CacheOptions>);
  constructor(namespace: string, options?: Partial<CacheOptions>);
}

// 如果不传命名空间，默认 'default'。

const memory = new Cache();
const memory2 = new Cache(options);
const memory3 = new Cache('namespace', options);

const local = new Storage({ storage: window.localStorage });
const local2 = new Storage('namespace', { storage: window.localStorage });

const session = new Storage({ storage: window.sessionStorage });
const session2 = new Storage('namespace', { storage: window.sessionStorage });
```

### CacheOptions

| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| storage | 自定义数据存储器，支持 `localStorage` `sessionStorage`。默认使用内置的内存缓存。 | `TStorage` | - |
| max | 最大缓存数据数量。`-1` 表示无限制。 | `number` | `-1` |
| maxStrategy | 当达到最大缓存数量限制时的缓存策略。<br/>`'limited'` 表示达到限制数量后不存入数据，保存时返回 `false`。<br/> `'replaced'` 表示优先替换先存入的数据，保存时返回 `true`。 | `'limited' \| 'replaced'` | `'limited'` |
| stdTTL | 相对当前时间的数据存活时间，应用于当前实例的所有缓存数据。单位为毫秒，`0` 表示无期限。 | `number` | `0` |
| checkperiod | 定时检查过期数据，单位毫秒。如果小于等于 `0` 表示不启动定时器检查。 | `number` | `0` |
| needParsed | 存取数据时是否需要序列化和解析数据。<br/>如果使用内置的内存缓存，默认 `false`，如果自定义 `storage` 默认 `true`。 | `boolean` | - |
| replacer | 数据存储时序列化的参数，透传给 [JSON.stringify](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) 的 `replacer` 参数。<br/>仅在 `needParsed=true` 时生效。 | `(key: string, value: any) => any` | - |
| reviver | 数据获取时转换的参数，透传给 [JSON.parse](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) 的 `reviver` 参数。<br/>仅在 `needParsed=true` 时生效。 | `(key: string, value: any) => any` | - |
| prefix | 缓存键前缀。 | `string` | `cache2_` |

<mark>⚠️ 注意：同一个命名空间的缓存是共享的。意味着命名空间名称相同的情况下，不同实例之间共用同一份缓存数据。建议自定义命名空间名称，避免不同实例的缓存数据冲突</mark>

### Cache 实例方法

```typescript
import { Cache } from 'cache2';
const myCache = new Cache(namespace?, options?);
```

### set(key: string, value: any, ttl?: number)

设置缓存数据。

如果设置成功返回 `true`，否则返回 `false`。

```typescript
myCache.set('myKey', { foo: 'bar', baz: 42 }, 5 * 60 * 1000);
// true
```

### mset(keyValueSet: {key: string, value: any, ttl?: number}[])

设置多个缓存数据。

如果全部设置成功返回 `true`，否则返回 `false`。

```typescript
myCache.mset([
  { key: 'myKey', value: { foo: 'bar', baz: 42 }, ttl: 5 * 60 * 1000 },
  { key: 'myKey2', value: { a: 1, b: 2 } },
  { key: 'myKey3', value: 'abc' }
]);
// true
```

### get(key: string)

获取缓存值。

如果找到该值，则返回该值。如果未找到或已过期，则返回 `undefined`。

```typescript
myCache.set('myKey', obj, 5 * 60 * 1000);
myCache.get('myKey');
// { foo: 'bar', baz: 42 }

myCache.get('myKey2');
// undefined
```

### take(key: string)

获取缓存值并从缓存中删除键。

如果找到该值，则返回该值，并从缓存中删除该键。如果未找到或已过期，则返回 `undefined`。

```typescript
myCache.set('myKey', 'myValue'); // true
myCache.has('myKey'); // true

myCache.take('myKey'); // 'myValue'
myCache.has('myKey'); // false
```

### mget(keys: string[])

获取多个缓存值。

如果找到对应键名的值，返回一个具有键值对的对象。如果未找到或已过期，则返回一个空对象 `{}`。

```typescript
myCache.mset([
  { key: 'myKey', value: { foo: 'bar', baz: 42 }, ttl: 5 * 60 * 1000 },
  { key: 'myKey2', value: { a: 1, b: 2 } },
  { key: 'myKey3', value: 'abc' }
]);

myCache.mget(['myKey', 'myKey2']);
// {
//   myKey: { foo: 'bar', baz: 42 },
//   myKey2: { a: 1, b: 2 }
// }
```

### getAll()

获取全部缓存值。

返回一个具有键值对的对象。

```typescript
myCache.mset([
  { key: 'myKey', value: { foo: 'bar', baz: 42 }, ttl: 5 * 60 * 1000 },
  { key: 'myKey2', value: { a: 1, b: 2 } },
  { key: 'myKey3', value: 'abc' }
]);

myCache.getAll();
// {
//   myKey: { foo: 'bar', baz: 42 },
//   myKey2: { a: 1, b: 2 }
//   myKey3: 'abc'
// }
```

### keys()

获取全部键名的数组。

返回全部键名的数组。

```typescript
myCache.set('bar', 1);
myCache.set('foo', 2);

myCache.keys(); // ['bar', 'foo']
```

### has(key: string)

判断是否存在某个键。

如果包含该键返回 `true`，否则返回 `false`。

```typescript
myCache.has('foo'); // false

myCache.set('foo', 1);
myCache.has('foo'); // true
```

### del(key: string|string[])

删除一个或多个键值。

返回已删除的数量。

```typescript
myCache.set('myKey', { foo: 'bar', baz: 42 });
myCache.del('myKey'); // 1
myCache.del('not found'); // 0

myCache.mset([
  { key: 'myKey', value: { foo: 'bar', baz: 42 }, ttl: 5 * 60 * 1000 },
  { key: 'myKey2', value: { a: 1, b: 2 } },
  { key: 'myKey3', value: 'abc' }
]);
myCache.del(['myKey', 'myKey2']); // 2
```

### clear()

清除全部缓存的数据（当前命名空间）。

```typescript
myCache.set('bar', 1);
myCache.set('foo', 2);
myCache.keys(); // ['bar', 'foo']

myCache.clear();

myCache.keys(); // []
```

### ttl(key: string, ttl: number)

更新缓存键值的数据存活时间。

```typescript
myCache.set('myKey', { foo: 'bar', baz: 42 }, 5 * 60 * 1000);
myCache.ttl('myKey', 2 * 60 * 1000);
// true

myCache.ttl('not found', 1000);
// false
```

### getTtl(key: string)

获取某个键的过期时间戳。有以下返回值：

- 如果未找到键或已过期，返回 `undefined`。
- 如果 `ttl` 为 `0`，返回 `0`。
- 否则返回一个以毫秒为单位的时间戳，表示键值将过期的时间。

```typescript
const myCache = new Cache({ stdTTL: 5 * 1000 });

// 假如 Date.now() = 1673330000000
myCache.set('ttlKey', 'expireData');
myCache.set('noTtlKey', 'nonExpireData', 0);

myCache.getTtl('ttlKey'); // 1673330005000
myCache.getTtl('noTtlKey'); // 0
myCache.getTtl('unknownKey'); // undefined
```

### getLastModified(key: string)

获取某个键值的最后修改时间。有以下返回值：

- 如果未找到键或已过期，返回 `undefined`。
- 否则返回一个以毫秒时间戳，表示键值最后修改时间。

```typescript
const myCache = new Cache();

// Date.now() = 1673330000000
myCache.set('myKey', 'foo');
myCache.getLastModified('myKey'); // 1673330000000

// 5000ms later ...
myCache.set('myKey', 'bar');
myCache.getLastModified('myKey'); // 1673330005000
```

### startCheckperiod()

启动定时校验过期数据。

注意，如果没有设置 `checkperiod` 将不会触发定时器。

```typescript
// 设置 checkperiod 之后自动生效
const myCache = new Cache({
  checkperiod: 10 * 60 * 1000 // 10分钟检查一次数据是否过期
});

// 停止定时校验过期数据
myCache.stopCheckperiod();

// 启动定时校验过期数据
myCache.startCheckperiod();
```

### stopCheckperiod()

停止定时校验过期数据。参考 `startCheckperiod` 示例。

### 自定义事件

#### set

成功设置键值后触发。

```typescript
myCache.on('set', (key, value) => {
  // do something
});
```

#### del

删除键值后触发。

```typescript
myCache.on('del', (key, value) => {
  // do something
});
```

#### expired

校验数据过期后触发。

注意，如果校验数据过期，会先删除数据触发 `del` 事件，然后再触发 `expired` 事件。

```typescript
myCache.on('expired', (key, value) => {
  // do something
});
```

## 应用场景

### 缓存接口数据

```typescript
import { Cache } from 'cache2';

const apiCache = new Cache('api', { stdTTL: 10 * 60 * 1000 });
// ...
```

### 缓存 URL.createObjectURL 预览文件，删除时 URL.revokeObjectURL 释放缓存

```typescript
import { Cache } from 'cache2';

const fileObjectUrlCache = new Cache('fileObjectUrl', { max: 20, maxStrategy: 'replaced' });
fileObjectUrlCache.on('del', (key, value) => {
  URL.revokeObjectURL(value);
});

fileObjectUrlCache.set(fssid, URL.createObjectURL(file));
```

### `sessionStorage`、`localStorage` 支持过期时间

```typescript
import { Cache } from 'cache2';

const localCache = new Cache({
  storage: localStorage,
  stdTTL: 5 * 60 * 1000 // 默认数据留存时间为5分钟
});

localCache.set('num', 1); // 该数据默认留存5分钟
localCache.set('str', 'foo', 10 * 60 * 1000); // 该数据留存10分钟
```

### 如何自定义一个 storage

自定义 `storage` 对象需要包含 `getItem` `setItem` `removeItem`。

例如，微信端的同步缓存等。

```typescript
import { Cache } from 'cache2';

const wxStorage = {
  getItem(key: string) {
    return wx.getStorageSync(key);
  },
  setItem(key: string, value: any) {
    wx.setStorageSync(key, value);
  },
  removeItem(key: string) {
    wx.removeStorageSync(key);
  }
};
const wxCache = new Cache('namespace', {
  storage: wxStorage,
  needParsed: false,
  stdTTL: 5 * 60 * 1000 // 设置默认数据留存时间为5分钟
});

wxCache.set('num', 1); // 该数据默认留存5分钟
wxCache.set('str', 'foo', 10 * 60 * 1000); // 该数据留存10分钟
```

### 使用对象作为缓存键

可以单独实现一个获取缓存键的方法。

```typescript
import { isObject } from 'ut2';

const wm = new WeakMap();
const getCacheKey = (obj: string | Blob) => {
  if (!isObject(obj)) {
    return String(obj);
  }
  if (!wm.get(obj)) {
    const key = '_' + Date.now();
    wm.set(obj, key);
  }
  return wm.get(obj) as string;
};

const myCache = new Cache('namespace');

myCache.set(getCacheKey(someKey), someValue);
myCache.get(getCacheKey(someKey));
```

[npm]: https://img.shields.io/npm/v/cache2.svg
[npm-url]: https://npmjs.com/package/cache2

---
_Source: https://npm.io/package/cache2 · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
