axios 原始碼取消請求解析
阿新 • • 發佈:2022-03-07
axios有兩種中斷請求的方法
1.CancelToken.source
const CancelToken = axios.CancelToken; const source = CancelToken.source();axios.post('/test', { value: '測試' }, { cancelToken: source.token })
source.cancel('取消請求');
2.通過CancelToken
建構函式進行取消
const CancelToken = axios.CancelToken; let cancel; axios.get("/test/user", { cancelToken: new CancelToken(function executor(c){ cancel = c }) }) cancel("取消請求")
主要程式碼:
function CancelToken(executor) { if (typeof executor !== 'function') { throw new TypeError('executor must be a function.'); } var resolvePromise; //給例項繫結一個promise,promsie 狀態為pending,只有呼叫resolvePromise 方法時this.promise變為fulfilled狀態this.promise = new Promise(function promiseExecutor(resolve) { resolvePromise = resolve; }); var token = this; // eslint-disable-next-line func-names this.promise.then(function(cancel) { if (!token._listeners) return; var i; var l = token._listeners.length; for (i = 0; i < l; i++) { token._listeners[i](cancel); } token._listeners= null; }); // eslint-disable-next-line func-names this.promise.then = function(onfulfilled) { var _resolve; // eslint-disable-next-line func-names var promise = new Promise(function(resolve) { token.subscribe(resolve); _resolve = resolve; }).then(onfulfilled); promise.cancel = function reject() { token.unsubscribe(_resolve); }; return promise; }; //通過Cancel函式創造一個取消原因資訊 executor(function cancel(message) { if (token.reason) { // Cancellation has already been requested return; } //token.reason 就是我們呼叫cancel方法時傳遞的資訊 token.reason = new Cancel(message); resolvePromise(token.reason); }); }
CancelToken.source = function source() { var cancel; var token = new CancelToken(function executor(c) { cancel = c; }); return { token: token, cancel: cancel }; };
在CancelToken.js中,發現上面兩種中斷請求的方法執行的都是同一個方法,
executor(function cancel(message) { if (token.reason) { // Cancellation has already been requested return; } token.reason = new Cancel(message); resolvePromise(token.reason); });
function Cancel(message) { this.message = message; }
token是指建立的CancelToken例項,判斷是否有reason這個屬性,有則說明已經發起取消請求了直接return,沒有就通過Cancel建構函式建立一個例項, 呼叫resolvePromise方法。
var resolvePromise; this.promise = new Promise(function promiseExecutor(resolve) { resolvePromise = resolve; });
在建立CancelToken例項時,新增一個屬性promise為Promsie的 例項,且狀態為pending,將resolve方法賦值給resolvePromise.這樣resolvePromise就像取消請求的開關,只有呼叫了resolvePromsie方法才能執行promise鏈.
if (config.cancelToken || config.signal) { // Handle cancellation // eslint-disable-next-line func-names onCanceled = function(cancel) { if (!request) { return; } reject(!cancel || (cancel && cancel.type) ? new Cancel('canceled') : cancel); request.abort(); request = null; };
config.cancelToken && config.cancelToken.subscribe(onCanceled);
CancelToken.prototype.subscribe = function subscribe(listener) { if (this.reason) { listener(this.reason); return; } if (this._listeners) { this._listeners.push(listener); } else { this._listeners = [listener]; } };
xhr.js根據cancelToken呼叫subscribe方法,當this.reason存在時呼叫 XMLhttpRquest取消方法。this.reason就是前面Cancel生成的例項。
以上就是axios取消請求的基本流程,