Сценарии, встречающиеся в проекте,
change
Когда событие вызывает нечеткое совпадение, за короткий промежуток времени отправляется несколько сообщений.ajax
запрос, последние возвращенные данные могут не быть последним триггеромchange
При выполнении запроса полученные данные не совпадают
решение
в использованииAxios
Чтобы сделать запрос данных, используйтеcancel token
отменить запрос
Официальный случайgithub.com/axios/axios
// using the CancelToken.source factory
const CancelToken = axios.CancelToken
const source = CancelToken.source()
// get
axios.get('/user/1', {
cancelToken: source.token
}).catch(function (thrown) {
if(axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message)
} else {
// handle error
}
})
// post
axios.post('/user/1', {
name: ''
}, {
cancelToken: source.token
})
// cancel request 参数可选
source.cancel('取消上次请求')
// use executor function
const CancelToken = axios.CancelToken
let cancel
// get
axios.get('/user/1', {
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c
})
})
// post
axios.post('/user/1', {
name: ''
}, {
cancelToken: new CancelToken(function executor(c) {
cancel = c
})
})
// cancel request
cancel()
мой
Vue
Пример проекта
import axios from 'axios'
let cancel
let CancelToken
mounted() {
CancelToken = axios.CancelToken
}
// 多次触发fetchList请求 取消上次请求,触发最新请求
async fetchList() {
if(cancel) {
cancel()
}
await axios.post('/user/list', {
query: ''
}, {
cancelToken: new CancelToken(function executor(c) {
cancel = c
})
})
}
родной XHR
оригинальный
XHR
объект называетсяabort()
метод отменыajax
просить
let xhr
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest()
} else {
xhr = new ActiveXObject('Microsoft.XMLHTTP')
}
xhr= new XMLHttpRequest()
xhr.open('GET', 'https://api')
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// success
} else {
// error
}
}
// 取消ajax请求 readyState = 0
xhr.abort()
Axios
Анализ источника светаCancelToken
axios/lib/cancel/CancelToken.js
'use strict';
var Cancel = require('./Cancel');
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
/**
* 定义 resolvePromise
* 新建promise实例
* 将 promise的resolve方法赋值给 resolvePromise 目的是为了在promise对象外使用resolvePromise方法来改变对象状态
*/
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
/**
* 将CancelToken实例赋值给token
* 给executor传入cancel方法,cancel可调用resolvePromise方法
*/
var token = this;
executor(function cancel(message) {
if (token.reason) {
// 取消已响应 返回
return;
}
token.reason = new Cancel(message);
// 这里执行的就是promise的resolve方法,改变状态
resolvePromise(token.reason);
});
}
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
if (this.reason) {
throw this.reason;
}
};
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
// c 就是CancelToken中给executor传入的cancel方法
cancel = c;
});
return {
token: token,
cancel: cancel
};
};
module.exports = CancelToken;
воплощать в жизнь
promise.resolve()
Как отменить послеajax
просить
- будет
CancelToken
добавить вaxios
изCancelToken
атрибут
// axios/lib/axios.js
axios.Cancel = require('./cancel/Cancel');
axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel');
-
CancelToken
изresolve
триггеры методаpromise.then
метод
// axios/lib/adapters/xhr.js
// 创建XHR对象
var request = new XMLHttpRequest()
// 模拟当前ajax请求
request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true)
if (config.cancelToken) {
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
// 取消ajax请求
request.abort();
reject(cancel);
// Clean up request
request = null;
});
}