一. 利用axios的cancelToken
import { $post } from 'util/ajax';
import axios from 'axios';
const CancelToken = axios.CancelToken;
// post
let cancel;
export const getData = data => dispatch => {
if (cancel !== undefined) {
cancel();
}
$post({
url: '',
data,
cancelToken: new CancelToken(c => { cancel = c; })
}).then(res => {
if (res) {
} else {
throw Error();
}
}).catch(error => {
if (axios.isCancel(error)) {
} else {
console.log(`异常: ${error}`);
}
});
};
// get
let cancel;
export const getData = params => dispatch => {
let type = '';
if (cancel !== undefined) {
cancel();
}
$get({
url: '',
params,
cancelToken: new CancelToken(c => { cancel = c; })
})
.then(res => {
})
.catch(err => {
});
};
二. 通过变量的作用域来控制
- 设置一个全局变量,例如
let globalIndex1 = 0
; 该变量只要不重新刷新浏览器就会保留在内存中。
- 再在函数内设置一个局部变量,
const curIndex = ++globalIndex1
;
- 理论上来说,任何时候curIndex 和 globalIndex1都是相等的;
- 但是接下来我们会在异步队列中使用这两个变量;
- 由于globalIndex1为全局的,所以在函数中使用它时,拿到的都是最新的,而curIndex由于为局部变量,它的值为当前函数作用域中的值;
- 故:只有当异步队列为空的时候,curIndex 和 globalIndex1才是相等的。
- 而curIndex 和 globalIndex1相等时,说明最后一次tab点击和最后一次ajax请求吻合上了。
let globalIndex1 = 0;
export const getGridData = params => dispatch => {
const curIndex = ++globalIndex1;
const finish = () => curIndex === globalIndex1 && dispatch(actionCreator(UPDATE_DATA)({}));
$get({
url: '',
params
}).then(res => {
finish();
}).catch(finish);
};
举例分析第二个方案:
let globalIndex1 = 0;
export const getGridData = params => dispatch => {
// 块1
const curIndex = ++globalIndex1;
const finish = () => curIndex === globalIndex1 && dispatch(actionCreator(UPDATE_DATA)({}));
// 块2
$get({
url: '',
params
}).then(res => {
finish();
}).catch(finish);
};
假如有两个tab,tab1和tab2
-
当点击tab1,调用getGridData,
在块1:
此时globalIndex1为1,curIndex=1
在块2:
将$get放入异步队列
-
当点击tab2,调用getGridData,
在块1:
此时globalIndex1为2,curIndex=2
在块2:
将$get放入异步队列
-
当点击tab1,调用getGridData,
在块1:
此时globalIndex1为3,curIndex=3
在块2:
将$get放入异步队列
- 如果只执行1, 那异步回来之后,此时curIndex和globalIndex1相等,执行dispatch;
- 如果执行1和2,且执行完2后,1的异步还没有回来,那么此时curIndex为1,globalIndex1为2,不相等;从队列继续获取第二个异步操作,此时curIndex为2,globalIndex1也为2,相等,故执行dispactch
// 进一步简化
<script>
let i = 0; // 全局变量
const fn = () => {
// k为局部变量
let k = ++i;
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 10);
});
p.then(res => {
console.log('k', k);
console.log('i', i);
})
};
fn()
fn()
fn()
fn()
/**
* 执行fn为同步的,所以执行4次fn i已经变成了4,然后再执行异步队列里的代码
*/
</script>
参考链接:
- https://segmentfault.com/a/1190000039844280
- https://www.npmjs.com/package/axios