前言
在开发中,经常会遇到接口重复请求导致的各种问题。
对于重复的get请求,会导致页面更新多次,发生页面抖动的现象,影响用户体验。
对于重复的post请求,会导致在服务端生成两次记录(例如生成两条订单记录)。
如果当前页面请求还未响应完成,就切换到了下一个路由,那么这些请求直到响应返回才会中止。
无论从用户体验或者从业务严谨方面来说,取消无用的请求确实是需要避免的。
当然我们可以通过页面loading来避免用户进行下一次的操作,但本文只讨论单纯的如何取消这些无用的请求。
axios 的 cancelToken
axios是一个主流的http请求库,它提供了两种取消请求的方式。
通过axios.CancelToken.source生成取消令牌token和取消方法cancel
const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios.get('/user/12345', { cancelToken: source.token }).catch(function(thrown) { if (axios.isCancel(thrown)) { console.log('Request canceled', thrown.message); } else { // handle error } }); axios.post('/user/12345', { name: 'new name' }, { cancelToken: source.token }) // cancel the request (the message parameter is optional) source.cancel('Operation canceled by the user.');
通过axios.CancelToken构造函数生成取消函数
const CancelToken = axios.CancelToken; let cancel; axios.get('/user/12345', { cancelToken: new CancelToken(function executor(c) { // An executor function receives a cancel function as a parameter cancel = c; }) }); // cancel the request cancel();
需要注意的是在catch中捕获异常时,应该使用axios.isCancel()判断当前请求是否是主动取消的,以此来区分普通的异常逻辑。
封装取消请求逻辑
上面有两种取消请求,用哪种都是可以的,这里使用第二种。
取消请求主要有两个场景:
- 当请求方式method,请求路径url,请求参数(get为params,post为data)都相同时,可以视为同一个请求发送了多次,需要取消之前的请求
- 当路由切换时,需要取消上个路由中未完成的请求
我们封装几个方法:
// 声明一个 Map 用于存储每个请求的标识 和 取消函数 const pending = new Map() /** * 添加请求 * @param {Object} config */ const addPending = (config) => { const url = [ config.method, config.url, qs.stringify(config.params), qs.stringify(config.data) ].join('&') config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => { if (!pending.has(url)) { // 如果 pending 中不存在当前请求,则添加进去 pending.set(url, cancel) } }) } /** * 移除请求 * @param {Object} config */ const removePending = (config) => { const url = [ config.method, config.url, qs.stringify(config.params), qs.stringify(config.data) ].join('&') if (pending.has(url)) { // 如果在 pending 中存在当前请求标识,需要取消当前请求,并且移除 const cancel = pending.get(url) cancel(url) pending.delete(url) } } /** * 清空 pending 中的请求(在路由跳转时调用) */ export const clearPending = () => { for (const [url, cancel] of pending) { cancel(url) } pending.clear() }
Map是ES6中一种新型的数据结构,本身提供了诸多方法,方便操作,适合当前场景。如果不熟悉的可以查看ECMAScript 6 入门。
在给config.cancelToken赋值的时候,需要判断当前请求是否已经在业务代码中使用了cancelToken
qs是一个专门用来转换对象和字符串参数的库,最初是由 TJ 创建并维护的,也是axios推荐使用的参数序列化库。这里我们的目的只是单纯的将参数对象转换为字符串方便拼接。
Map结构默认部署了Symbol.iterator属性,可以使用for...of循环直接获取键名和键值,当然你也可以使用for...in循环。
在 axios 拦截器中使用
主要的方法已经写好了,只需要添加到axios拦截器中就可以了。
axios.interceptors.request.use(config => { removePending(options) // 在请求开始前,对之前的请求做检查取消操作 addPending(options) // 将当前请求添加到 pending 中 // other code before request return config }, error => { return Promise.reject(error) }) axios.interceptors.response.use(response => { removePending(response) // 在请求结束后,移除本次请求 return response }, error => { if (axios.isCancel(error)) { console.log('repeated request: ' + error.message) } else { // handle error code } return Promise.reject(error) })
将clearPending()方法添加到vue路由钩子函数中
router.beforeEach((to, from, next) => { clearPending() // ... next() })
测试效果
最后我们可以在浏览器中测试下,可以将chrome中控制面板的Network的网络状态切换为Slow 3G来模拟网速慢的情况。
我们把查询按钮的loading或者disabled属性干掉来方便测试
在上面控制面板中可以看到,红色的status为canceled的就是被取消的请求。
上面代码在e-admin-vue(一个使用 vue + element-ui + vue-cli3 构建的 rbac 权限模型)或者e-admin-react(一个使用 react + antd + create-react-app 构建的 rbac 权限模型)中都有体现,欢迎 star。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]