vue路由切换时取消之前的所有请求操作在main.js⽂件⾥
import router from 'router/';
i mport Vue from 'vue';
Vue.Cancel = [];
router.beforeEach((to, from, next) => {
while (Vue.Cancel.length > 0) {
Vue.Cancel.shift()('cancel');
}
next();
})
ajax⽂件
import Vue from 'vue';
import axios from 'axios';
import VueAxios from 'vue-axios';
Vue.use(VueAxios, axios);
// 导⼊封装的回调函数
import {
cbs,
gbs
} from 'config/';
// 动态设置本地和线上接⼝域名
Vue.axios.defaults.baseURL = gbs.host;
/
**
* 封装axios的通⽤请求
* @param {string} type get或post
* @param {string} url 请求的接⼝URL
* @param {object} data 传的参数,没有则传空对象
* @param {object} urlParams url传参
* @param {Function} fn 回调函数
* @param {boolean} tokenFlag 是否需要携带token参数,为true,不需要;false,需要。⼀般除了登录,都需要
*/
export default function ({
type,
path,
data,
params,
urlParams,
fn,
errFn,
tokenFlag,
headers,
opts
} = {}) {
var options = {
method: type,
url: path,
params: params,
headers: headers && typeof headers === 'object' ? headers : {},
cancelToken: new axios.CancelToken(function (cancel) {
Vue.Cancel && Vue.Cancel.push(cancel)
})
};
//检测接⼝权限
var api_flag = true;
if (options.url && options.url.indexOf(gbs.host) && this.$store.state.user.userinfo.access_status === 1) {
var url = place(gbs.host, '');
var api_routers = this.$store.state.user.userinfo.api_routers;
if (!api_routers || !structor === Object || !api_routers[url]) {
api_flag = false;
}
}
var urlParamsArray = [];
if (api_flag === true) {
options[type === 'get' ? 'params' : 'data'] = data;
// ⽤于url传参
if (typeof (urlParams) == "object") {
for (var k in urlParams) {
urlParamsArray.push(k + '=' + urlParams[k])
}
options.url += '?' + urlParamsArray.join('&');
}
if (typeof (urlParams) == "string" || typeof (urlParams) == "number") {
options.url += urlParams;
}
if(options.url.indexOf('?') > -1){
options.url += '&_=' + (new Date()).getTime();
}else{
options.url += '?_=' + (new Date()).getTime();
}
// 分发显⽰加载样式任务
this.$store.dispatch('show_loading');
if (tokenFlag !== true) {
//如果你们的后台不会接受headers⾥⾯的参数,打开这个注释,即实现token通过普通参数⽅式传
// ken = this.$store.state.ken;
ken = this.$store.state.ken;
}
//扩展Promise使⽀持finally(),⽤了babel就不⽤⼿写了^.^
// Promise.prototype.finally=function(callback){
/
/ let Promise = structor;
// return this.then(
// value => solve(callback()).then(() => value),
// reason => solve(callback()).then(() => { throw reason })
// );
// };
//发送请求
return new Promise((resolve, reject)=>{
Vue.axios(options).then((res) => {
this.$store.dispatch('hide_loading');
if (res.data[gbs.api_status_key_field] === gbs.api_status_value_field || (res.status === gbs.api_status_value_field && !res.data[gbs.api_status_key_field])) { fn(res.data);
} else {
if (gbs.api_custom[res.data[gbs.api_status_key_field]]) {
gbs.api_custom[res.data[gbs.api_status_key_field]].call(this, res.data);
} else {
cbs.statusError.call(this, res.data);
if (errFn) {
errFn.call(this, res.data);
}
}canvas动画
}
resolve(res.data);
}).catch((err) => {
sponse && sponse.status !== 403){
try{
errFn?errFn.call(this, this.$$lib__.sponse.data) ? sponse.data : {}):null;
}catch(err){
<(ssage);
}
}
sponse && sponse.data === ''){
cbs.statusError.call(this, {status: sponse.status});
} else if (sponse && this.$$lib__.sponse.data)) {
cbs.statusError.call(this, sponse.data);
}else sponse){
} else {
<('Error from ', '"'+path+'".', ssage);
}
reject(err);
});
});
} else {
this.$alert('您没有权限请求该接⼝!', '请求错误', {
confirmButtonText: '确定',
type: 'warning'
});
}
};
核⼼代码为cancelToken参数
var options = {
method: type,
url: path,
params: params,
headers: headers && typeof headers === 'object' ? headers : {},
cancelToken: new axios.CancelToken(function (cancel) {
Vue.Cancel && Vue.Cancel.push(cancel)
})
};
补充知识:problem:vue组件局部刷新,在组件销毁(destroyed)时取消刷新⽆效问题
场景:
⼀个发消息列表(数组)
列表下有多条消息(元素)
每条正在发送的消息数据状态需要实时刷新,发送完成时需要显⽰成功提⽰符合且不需要刷新,然后3秒消失。⾸次显⽰列表时,已经成功的状态不显⽰这个成功提⽰符。
1、定位确定采⽤局部刷新
2、进⼊消息列表请求获取列表数据的接⼝,完成发送的消息不需显⽰完成状态
3、正在发送的消息⾸次渲染时就调⽤setTimeout轮询刷新当前消息的接⼝,完成时,显⽰完成状态(新增⼀个完成状态的字段)
4、页⾯销毁时,还在发送的消息也取消刷新
误区:
1、每条消息没有抽成⼀个单独的组件,想要⾸次渲染组件调⽤刷新接⼝时,只能通过定义全局map变量来映射每条消息的刷新接⼝的定时器,明显增加业务开发的复杂度,增加了⼀些不确定性的bug风险。
每条消息抽成组件之后,就可以在组件中的mounted中去调⽤刷新的接⼝,页⾯销毁时取消刷新可以在destroyed⾥⾯去销毁。
2、这⾥的⼀个误区是在destroyed⾥⾯去清除定时器的id,导致调⽤了destroyed钩⼦刷新的定时器还是⽆法清除。将定时器id当做⼀个属性值存在了每条数据所属的对象中,然后在⼦组件(每条消息所属的)中的destroyed中去读取该对象的当前的定时器属性,因为读出来是undifined,其实并没有拿到当前消息正在执⾏的定时器,所以清除不掉。
组件使⽤有误,每⼀个组件都是⼀个独⽴的元素,其中定义的变量也是私有的,定时器id定在当前组
件的data中就可以了,不需要再在数组中的每⼀条消息中定⼀个专属的定时器id。
抽象出来的简单版刷新数据,5秒后取消刷新。
let intervalId = null
function init() {
}
function refresh() {
intervalId = setTimeout(() => {
}, 2000);
}
function getRefreshData() {
console.log('start ', intervalId)
setTimeout(() => {
console.log('')
}, 100);
}
function stopRefresh() {
console.log('', intervalId)
clearInterval(intervalId)
}
this.init()
setTimeout(() => {
this.stopRefresh()
}, 5000);
以上这篇vue路由切换时取消之前的所有请求操作就是⼩编分享给⼤家的全部内容了,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论