想问一下 pinia 持久化到 localStorage 如何实现有效期

83 天前
 puremaker

RT ,本人做了款小游戏,把玩家信息存到了 store 里。但是发现如果某个玩家意外退出了,且游戏对局结束了,当这个玩家再打开页面的时候还会被识别为在游戏中,因为他没有经历正常的结束游戏代码,没有去移除掉失效的玩家信息。当然每次重载游戏的时候用玩家信息去核实游戏状态也可以。但是我想知道这个持久化到底能不能设置有效期

2168 次点击
所在节点    Vue.js
10 条回复
Troevil
83 天前
自己封装一下

第一种用额外的 key ,val 存储 key 的过期时间
```typescript
// stores/user.ts
import { defineStore } from 'pinia'

const EXPIRATION_KEY = '__user_store_expire__'
const EXPIRATION_DURATION = 1000 * 60 * 60 // 1 小时(可修改)

export const useUserStore = defineStore('user', {
state: () => ({
name: '',
token: '',
}),
persist: {
key: 'user', // 本地存储的 key
storage: localStorage,
afterRestore: (context) => {
const expireTime = parseInt(localStorage.getItem(EXPIRATION_KEY) || '0')
const now = Date.now()
if (now > expireTime) {
console.log('user store expired, resetting...')
context.store.$reset()
localStorage.removeItem(EXPIRATION_KEY)
}
},
// 在每次存储后写入过期时间
beforeRestore: () => {
const expireTime = Date.now() + EXPIRATION_DURATION
localStorage.setItem(EXPIRATION_KEY, expireTime.toString())
}
},
})

```

第二种 直接 warpper 原数据
```
// stores/user.ts
import { defineStore } from 'pinia'
import { createPersistedState } from 'pinia-plugin-persistedstate'

// 设置过期时间(单位:毫秒)
const EXPIRE_TIME = 1000 * 60 * 60 // 1 小时

// 封装一个带过期逻辑的 storage
const expiredStorage = {
getItem: (key: string): string | null => {
const raw = localStorage.getItem(key)
if (!raw) return null

try {
const parsed = JSON.parse(raw)
const now = Date.now()

if (parsed.expire && now > parsed.expire) {
localStorage.removeItem(key)
return null
}

return JSON.stringify(parsed.data)
} catch (e) {
return null
}
},

setItem: (key: string, value: string): void => {
const payload = {
data: JSON.parse(value),
expire: Date.now() + EXPIRE_TIME,
}
localStorage.setItem(key, JSON.stringify(payload))
},

removeItem: (key: string): void => {
localStorage.removeItem(key)
},
}



```
runlongyao2
83 天前
原生 API 肯定没有,得自己加一个存储值
FrankFang128
83 天前
当用户来到你的首页,你就应该重置游戏信息了
DeWjjj
83 天前
存字段的时候就设置一个时间呗,然后上页面就存取,过期就去掉呗。
VVVYGD
83 天前
前端 localstoreage 与后端存储要做些同步,例如最终一致性。
chf007
83 天前
如果只是临时的游戏数据,可以换成持久在 sessionStorage 里么
xmdbb
83 天前
重新进入时候不应该通过对局 ID 查询对局状态吗....
好像和持久化有效期没关系吧...
SanjinGG
82 天前
看样子,游戏状态没必要持久化吧,你又不断线重新加入对局
heike8
81 天前
存对象加个 ts ,取的时候判断下
puremaker
80 天前
@xmdbb 正常情况是需要这样设计,我偷了懒,前端存在玩家 id 就认为游戏还在。以后会改

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1138410

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX