npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@wfp99/async-lru-cache

v1.1.1

Published

A simple memory cache using the LRU algorithm and supporting asynchronous data access.

Downloads

132

Readme

Async LRU Cache

npm version License: MIT Node.js Version

一個支援非同步載入和保存操作的 LRU(Least Recently Used)記憶體快取,自動處理並發請求。

特色

  • 🚀 非同步支援:支援非同步的載入器(loader)和保存器(saver)函數
  • 🔄 自動合併:自動合併相同 key 的並發 GET 請求
  • 📝 序列化寫入:序列化同一 key 的 PUT 操作,確保順序執行
  • 🗑️ LRU 淘汰策略:實現 LRU 演算法,自動移除最久未使用的項目
  • TTL 支援:支援可配置的生存時間(Time To Live),自動過期快取項目
  • 🛡️ 錯誤處理:完善的錯誤處理機制,失敗時自動清理快取
  • 🧹 完整清除:支援一次性清除所有快取項目

為什麼選擇記憶體內快取而非外部快取服務?

簡單性與效能

  • 無需設定 - 安裝後立即使用
  • 零網路延遲 - 直接記憶體存取
  • 減少基礎架構複雜性

可靠性與開發

  • 無外部依賴或網路故障風險
  • 簡化測試和除錯
  • 無需 Redis、Memcached 或其他快取伺服器

安裝

npm install @wfp99/async-lru-cache

系統需求

  • Node.js >= 14.0.0

使用方法

基本使用

import { AsyncLRUCache } from '@wfp99/async-lru-cache';

// 創建一個最多容納 100 個項目的快取
const cache = new AsyncLRUCache({
    capacity: 100
});

// 使用 get 方法獲取資料
const data = await cache.get('user:123', async () => {
    // 快取未命中時執行的載入器函數
    const response = await fetch('/api/users/123');
    return response.json();
});

// 使用 put 方法儲存資料
await cache.put('user:456', userData, async (key, value) => {
    // 可選的保存器函數,用於持久化資料
    await saveToDatabase(key, value);
});

錯誤處理

try {
    const data = await cache.get('problematic-key', async () => {
        throw new Error('載入失敗');
    });
} catch (error) {
    console.error('快取載入失敗:', error);
    // 失敗的項目會自動從快取中移除
}

TTL(生存時間)支援

AsyncLRUCache 支援使用 TTL(Time To Live)自動過期快取項目:

import { AsyncLRUCache } from '@wfp99/async-lru-cache';

// 建立支援 TTL 的快取
const cache = new AsyncLRUCache({
    capacity: 100,
    defaultTtlMs: 5000,        // 預設 TTL 為 5 秒
    cleanupIntervalMs: 10000   // 每 10 秒清理過期項目
});

// 使用預設 TTL
const data1 = await cache.get('key1', async () => {
    return await fetchData();
});

// 為特定項目覆寫 TTL
const data2 = await cache.get('key2', async () => {
    return await fetchCriticalData();
}, 30000); // 30 秒 TTL

// 使用自訂 TTL 進行 Put 操作
await cache.put('key3', value, async (key, val) => {
    await saveToDb(key, val);
}, 60000); // 1 分鐘 TTL

// 手動清理過期項目
cache.cleanupExpired();

// 檢查 key 是否存在且未過期
if (cache.has('key1')) {
    console.log('Key 存在且有效');
}

// 取得快取大小
console.log('目前快取大小:', cache.size());

// 銷毀快取(停止清理計時器並清除所有資料)
cache.destroy();

TTL 配置選項

  • defaultTtlMs:所有快取項目的預設 TTL(可選)
  • cleanupIntervalMs:過期項目的自動清理間隔(可選)
  • 個別的 get()put() 方法接受 TTL 覆寫
  • 過期項目在正常操作期間會自動移除
  • 呼叫 cleanupExpired() 進行手動清理
  • 呼叫 destroy() 停止計時器並防止記憶體洩漏

進階使用

// 與資料庫配合使用
const cache = new AsyncLRUCache<string, UserData>({ capacity: 500 });

// 從資料庫載入並自動快取
const user = await cache.get(`user:${userId}`, async () => {
    return await database.users.findById(userId);
});

// 原子性地保存到快取和資料庫
await cache.put(`user:${userId}`, updatedUser, async (key, value) => {
    await database.users.update(userId, value);
});

快取管理

// 手動移除特定快取項目
cache.invalidate('user:123');

// 清除所有快取項目
cache.clear();

API 參考

AsyncLRUCache<K, V>

建構函數

constructor(option: AsyncLRUCacheOption)

AsyncLRUCacheOption

| 屬性 | 類型 | 必需 | 描述 | |-----|------|------|------| | capacity | number | 是 | 快取中允許的最大項目數量,必須為正數 | | defaultTtlMs | number | 否 | 所有快取項目的預設 TTL(可選) | | cleanupIntervalMs | number | 否 | 過期項目的自動清理間隔(可選) |

方法

get(key: K, loader: () => Promise<V>, ttlMs?: number): Promise<V>

從快取中獲取資料。如果不存在,使用載入器載入資料。

  • key: 快取鍵
  • loader: 快取未命中時執行的非同步載入函數
  • ttlMs: 此項目的可選 TTL 覆寫
  • 回傳: Promise,解析為所需的資料
put(key: K, value: V, saver?: (key: K, value: V) => Promise<void>, ttlMs?: number): Promise<V>

將值放入快取中,並可選擇性地執行保存器函數進行持久化。

  • key: 快取鍵
  • value: 要快取的值
  • saver: 可選的非同步保存函數
  • ttlMs: 此項目的可選 TTL 覆寫
  • 回傳: Promise,解析為保存操作完成後的最新值
invalidate(key: K): void

使指定鍵的快取項目失效並移除。

  • key: 要失效的快取鍵
clear(): void

清除所有快取項目。此方法會移除快取中的所有項目並手動清理節點連結以避免潛在的記憶體洩漏。

has(key: K): boolean

檢查快取中是否存在指定鍵且未過期。

  • key: 要檢查的快取鍵
  • 回傳: 如果鍵存在且有效則回傳 true
size(): number

回傳快取中目前的項目數量。

  • 回傳: 快取項目的數量
cleanupExpired(): void

手動從快取中移除過期項目。

destroy(): void

銷毀快取,停止清理計時器並清除所有資料。

並發處理

AsyncLRUCache 會自動處理並發操作:

  • GET 請求合併:對同一 key 的多個並發請求會共享單一載入器執行
  • PUT 操作序列化:對同一 key 的多個 PUT 操作會序列化執行以確保順序
// 這三個並發請求會共享同一個載入器執行
const [data1, data2, data3] = await Promise.all([
    cache.get('shared-key', loader),
    cache.get('shared-key', loader),
    cache.get('shared-key', loader)
]);

// 這些操作會按順序執行,即使它們是並發啟動的
cache.put('key', 'value1', saver1);
cache.put('key', 'value2', saver2);
cache.put('key', 'value3', saver3);

TypeScript 支援

此套件完全使用 TypeScript 編寫,提供完整的型別支援:

interface User {
    id: string;
    name: string;
    email: string;
}

const userCache = new AsyncLRUCache<string, User>({
    capacity: 1000
});

const user: User = await userCache.get('user:123', async () => {
    // 載入器必須回傳 User 型別
    return fetchUserFromAPI('123');
});

錯誤處理

  • 載入器失敗:如果載入器函數拋出異常,對應的快取項目會被自動移除
  • 保存器失敗:如果保存器函數失敗,快取項目也會被移除,確保資料一致性
  • 操作鏈錯誤:PUT 操作會忽略前一個操作的錯誤,允許新操作繼續進行
  • 錯誤日誌:所有錯誤都會自動記錄到控制台,便於除錯

授權

MIT

貢獻

歡迎在 GitHub 上提出問題和發送 Pull Request。

作者

Wang Feng Ping