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

3 天前
 puremaker

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

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

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

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

https://ex.noerr.eu.org/t/1138410

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

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

© 2021 V2EX