一次页面请求loading转圈圈没停止bug的追踪
终极省流:项目中封装的请求方法存在问题,刷新token成功后,没把旧的请求结果返回到业务代码中,Promise一直处在pending状态,所以关闭loading方法一直没执行,导致一直在转圈圈
1. 项目背景
- uniapp 微信小程序项目
- 项目中采用JWT登录,登录成功后返回
access_token
和refresh_token
,其中access_token用于每次请求的时候在header中带上令牌,Authorization: Bearer {{access_token}}
,refresh_token用于access_token过期失效后刷新新的access_token - 网络请求采用的是基于
uni.request
自行封装的方法
2. 发现bug及分析
2.1 误会了mescroll-uni
- 发生bug的页面,是一个列表页,请求需要携带token的,列表里采用了mescroll-uni库(是专门用在uni-app的下拉刷新和上拉加载的组件, 支持一套代码编译到iOS、Android、H5、小程序等多个平台)
mescroll-uni简单使用示例
1 |
|
当access_token失效后,而这时候刚好点击进入到了这个列表页,而mescroll-uni在upOption中配置了
auto: true
(即初始化完毕之后自动执行上拉加载的回调),此时会走刷新token操作,token刷新成功后,会重新把刚才的请求走一遍,然后把结果返回给页面。问题就出现在这,由于封装的请求方法中的刷新token模块有问题,没有把重新请求的结果返回给页面,导致mescroll-uni一直在loading。而在微信开发者工具network中看到没任何问题,请求A返回code为4011,token失效,发起refresh_token请求,然后再次发送请求A,步骤没错。console控制台也没有任何报错。
当重新下拉刷新后,列表就重新渲染了(因为此时发起的请求,带的token已经是刷新过后的新token),这样造成我一度认为mescroll-uni库有bug,无语!
2.2 token刷新方法存在问题
一次偶然在请求前加了
uni.showLoading
,发现token刷新成功后,转圈圈居然还在,uni.hideLoading
未执行,让我恍然大悟,项目中自行封装的http
方法有问题
1 |
|
存在问题的http
请求方法代码片段:
1 |
|
分析:上面代码中可以看到,当返回4011 token失效后,refreshToken方法中,刷新token后,重新执行http方法发起请求,这时候的结果,没有resolve或者reject回去,导致页面那一次请求一直处在pending状态,而uni.request方法默认超时时间为60000ms(即1分钟),没等到1分钟,就手动离开这个页面了,导致超时的错误也没看到。refreshToken方法里虽然把那一次请求重新发出了,但这里就如同你用postman,请求成功与否和页面代码已无关
3. 无感刷新的修改
项目是中途接手,那就基于这个继续修改,就不替换了
两个注意点:
- 当access_token失效后,此时刷新token,要防止重复刷新,用一个变量控制
- 当access_token失效后,此时正在刷新token,如果页面中此时还有其它请求正在发出,需要存起来(Promise在pending状态),等token刷新成功后,再把刚才存起来的请求按顺序一个个拿出来,按顺序重新发起请求,并把结果返回给页面(把Promise状态改为fulfilled或者rejected状态)
改造后的完整代码片段:
1 |
|
4. 参考资料
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!