问题描述
我想把用户登录状态保存到LocalStorage, 所以一直用 uni.setStorageSync()
和 uni.getStorageSync()
, 但是昨天遇到了一个奇怪的问题 当用 uni.setStorageSync("Expired", true)
来设置用户已经过期后 , 启动时获取到的 uni.getStorageSync("Expired")
一直是true, 哪怕启动后我重新获取了状态并设置了 uni.setStorageSync("Expired", false)
, 可是启动依旧获取到true.
整整花费了1天时间最终只能用其他一种方式来解决.
复现步骤
微信H5(微信网页)使用中向第三方发送请求, 如果请求中带有过期请求, 我就跳转到一个网页:
// 跳转到处理Storage网页
uni.reLaunch({
url: '/pages/loading?id=-1'
});
网页中我直接尝试重新获取请求, 如果依旧失败则让Storage设置成过期. 这时候用户打开网页就提示过期了. 以下是loading.vue
<template>
`` 此处省略
</template>
<script>
export default {
data() {
return {
IsExpiredSource:false,
Message : "页面中的提示!"
}
},
components: {},
methods: {
async getdatas() {
// 像第三方请求获取登录状态
let hhgghse = await this.get('https://第三方网页/GetJson')
// 如果获取不到任何信息过期
if (!hhgghse.Id) {
this.Message = "获取不到信息"!
uni.hideLoading()
return
}
// 如果从第三方请求会话一样, 需要重新生成会话设置成过期(防止继续用老会话)
else if (this.IsExpiredSource)
{
let ddfer = uni.getStorageSync('gcook')
if (ddfer.SessionId== hhgghse.SessionId)
{
// 直接让设置为过期
uni.removeStorageSync('Expired')
uni.setStorageSync('Expired', true)
this.Message = "会话过期, 需要重新生成"!
uni.hideLoading()
return
}
}
uni.removeStorageSync('times')
uni.removeStorageSync('Expired')
// 去掉过期信息 (这里重新打开又不生效)
let sdee = new Date().getTime()
uni.setStorageSync('times', sdee)
uni.setStorageSync('Expired', false)
// 获取到的信息保存起来并跳转
uni.setStorage({
key: 'gcook',
data: hhgghse,
success: () => {
uni.showModal({
content: "数据重新获并保存!"
showCancel:false,
confirmText:this."OK",
success: function (res) {
uni.reLaunch({
url: '/pages/index/index',
success(){
//微信中去掉这个注解是解决问题的关键
//location.reload();
}
})
uni.hideLoading()
}
});
}
})
}
},
onLoad: () => {
},
mounted() {
uni.showLoading({
title: 'loader...'
})
// 如果请求中带-1需要把本地Session和服务器Session对比, 相同就代表过期, 用户需要重新生成认证后打开本网页
if (this.$route.query.id == -1)
{
this.IsExpiredSource = true
}
var ddfer = uni.getStorageSync('gcook')
this.getdatas()
}
}
</script>
<style lang='scss' scoped>
</style>
从上面的代码可以简单看到. 用户在网页做操作时会像第三方发送请求, 如果第三方突然给你发送你的会话过期了, 则用户需要跳转到固定的loading页面, 并重新获取一个网页数据(相当于令牌), 如果获取不到提示用户无法获取, 如果成功获取了先检查是否和本地一样, 如果一样就手动保存Storage过期信息, 免得用户重复发送其他请求给第三方网页(都过期了没那个必要), 直到用户获取新的会话前, 我们网页都无法进行其他操作. 这时候需要启动中加一些代码. App.vue中 :
<script>
export default {
methods: {
},
onLaunch() {
let ddfer = uni.getStorageSync('gcook')
let times = uni.getStorageSync('times')
let Expired = uni.getStorageSync('Expired')
// 缓存了8小时清除缓存
let cerertr = new Date().getTime()
// 如果是强制获取, 则需要直接跳转到相关页面检查对比第三方和本地会话
if (Expired == true)
{
uni.reLaunch({
url: '/pages/loading?id=-1'
});
}
// 超出了8小时重新获取第三方那边的新会话即可
else if((cerertr -times) >(1000*60*60*8) || !times)
{
uni.reLaunch({
url: '/pages/loading'
});
}
}
}
</script>
<style>
@import"static/css/style.css";
</style>
这个页面说明了, 用户打开网页时先不要跳转默认页, 先检查是否会话过期, 如果过期了跳转到loading..., 并获取第三方请求, 如果是Expired成立, 则获取第三方请求直到第三方和本地会话Id不一样位置.
现在重新说一下整个流程. 用户微信中打开网页(电脑上浏览器没问题), 用着用着, 突然获取了Expired过期这个结果, 跳转到了Loading?=id=-1页面, 检查第三方和本地会话发现会话一样, 则手动写入了 uni.setStorageSync("Expired", true)
, 用户只能关闭网页.
当用户第二次打开网页后获取uni.getStorageSync('Expired')发现过期, 又跳转到了Loading?=id=-1页面.但是如果用户在这个页面操作`uni.setStorageSync("Expired", false)并关闭网页重新打开, 刚这个操作失效了????
最后我发现直到第一个代码中的这个代码去掉注解(让它生效)刷新一下页面, 这样关闭网页下次打开上次保存的数据才会生效.....这算什么事儿??? (如果上上面的代码中找不到下面这行, 请自行Ctrl+F)
// 微信中去掉这个注解是解决问题的关键
//location.reload();
预期结果
微信打开后如果成功获取到了不一样的数据, 用 uni.setStorageSync("Expired", false)
保存后关闭网页, 下次打开时获取到的uni.getStorageSync('Expired')应该也是false.
实际结果
直到刷新页面, 否则微信刚打开就设置的 uni.setStorageSync("Expired", false)
, 根本不会生效.
系统信息:
- 发行平台: 微信里的网页(非小程序)
- 操作系统 iOS 13.4.1
- HBuilderX版本 2.6.16.20200424
- uni-app版本 在哪儿查?
- 设备信息 iphone 7
补充信息
我不知道这到底算什么逻辑? 难道说这是正常的吗? 我是说 微信中刚打开网页(非首次打开), 难道不刷新的话所有setStorageSync操作不会生效? 我是在是不能理解.
以上代码只是为了说明基本情况有去掉多余的代码, 如有什么问题 请留言讨论.
7条答案
按热度按时间bfnvny8b1#
我猜你肯定是忽略了你存布尔值实际存进去的是一个string,会被JSON.stringfy序列化
4smxwvx52#
你可以去除网络请求相关的描述,你想反馈的是不是setStorageSync存储一个Date对象然后用getStorageSync取出在部分浏览器中和预期不符?
ddhy6vgd3#
@EvanMaFYH , 这个错误我测试了无数次, 和bool类型无关, 因为我用string也是一样的结果.
@zhetengbiji , 你好像没听明白问题, 问题不是说存取和获取的值不同(因为使用中存储关闭后下次打开能正常获取), 而是刚启动时存储后不刷新页面直接关闭重新打开, 刚保存的不会生效, 这才是问题.
qvsjd97n4#
排除其他逻辑,你直接写一个新的工程单独测试storage接口是否存在问题。
如果单独测试能复现,试试其他设备能否复现。
jtoj6r0c5#
@zhetengbiji , 我还是直接像现在一样通过存储后强制刷新页面来解决吧. 我近期估计没有时间去专门做个项目测试这个. 即便新工程能复现问题, 解决方案还不是存储后还得强制刷新一遍页面.
fumotvh36#
@zhetengbiji , 我还是直接像现在一样通过存储后强制刷新页面来解决吧. 我近期估计没有时间去专门做个项目测试这个. 即便新工程能复现问题, 解决方案还不是存储后还得强制刷新一遍页面.
还是确定一下问题比较好,你所谓的“诡异”问题和奇特的”解决方案“,目前都还没有其他人提到过,有可能你哪里搞错了。
wz8daaqr7#
@zhetengbiji , 我如果搞错了应该Chrome测试也应该有问题. 目前只是在iphone上的微信H5才这样. 等更多人React再说吧那就.