码桶
发现社区成员的开源项目
sync.js2 KB
/**
* sync.js - Upstash Redis 数据同步层
* 在 localStorage 和 Upstash Redis 之间同步数据
*
* 工作原理:
* - init(): 页面加载时从 Redis 拉取最新数据,覆盖到 localStorage
* - save(): 数据变更时 fire-and-forget 推送到 Redis
* - 如果 Redis 不可用(本地开发),静默回退到纯 localStorage 模式
*/
const DataSync = {
kvAvailable: false,
initialized: false,
/**
* 从 Redis 拉取数据到 localStorage
* 前台和后台都会调用
*/
async init() {
if (this.initialized) return;
try {
const resp = await fetch('/api/data', { method: 'GET' });
if (!resp.ok) throw new Error('API error: ' + resp.status);
const data = await resp.json();
// 只在 Redis 有实际数据时覆盖 localStorage
// Redis 返回 null 表示尚未写入过,保留本地数据
if (data.domains !== null && data.domains !== undefined) {
localStorage.setItem('domain_market_data', JSON.stringify(data.domains));
}
if (data.config !== null && data.config !== undefined) {
localStorage.setItem('domain_market_site_config', JSON.stringify(data.config));
}
this.kvAvailable = true;
} catch (e) {
console.log('[DataSync] Redis not available, using localStorage only');
this.kvAvailable = false;
}
this.initialized = true;
},
/**
* 推送数据到 Redis(fire-and-forget)
* 仅在 Redis 可用且有有效 token 时执行
*/
save(key, value) {
if (!this.kvAvailable) return;
// 只有 API 模式的 token 才能写 Redis
const token = sessionStorage.getItem('admin_token');
if (!token || token.startsWith('local_')) return;
fetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify({ key, value })
}).catch(e => console.error('[DataSync] Redis sync failed:', e));
}
};