(Ajax)axios源码简析(三)——请求与取消请求
傳送門:
- axios源碼簡析(一)——axios入口文件
- axios源碼簡析(二)——Axios類與攔截器
- axios源碼簡析(三)——請求與取消請求
請求過程
在Axios.prototype.request中我們看到,要先通過請求攔截器,才能進行請求。下面看一下dispatchRequest()是如何實現的
// /lib/core/dispatchRequest.jsmodule.exports = function dispatchRequest(config) {// 判斷是否已經取消請求throwIfCancellationRequested(config);/* 對請求的url、headers、data進行處理 */// 發動請求的函數,返回一個promisevar adapter = config.adapter || defaults.adapter;return adapter(config).then(function onAdapterResolution(response) {// 判斷是否已經取消請求throwIfCancellationRequested(config);// 處理返回的數據response.data = transformData(response.data,response.headers,config.transformResponse);return response;}, function onAdapterRejection(reason) {if (!isCancel(reason)) {// 判斷是否已經取消請求throwIfCancellationRequested(config);// 處理返回的錯誤信息if (reason && reason.response) {reason.response.data = transformData(reason.response.data,reason.response.headers,config.transformResponse);}}return Promise.reject(reason);});如果用戶有在配置中傳入adapter,將使用defaults.adapter,根據運行環境是瀏覽器還是nodejs采取不同的請求方式。
// /lib/defaults.js function getDefaultAdapter() {var adapter;if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {// nodejs環境adapter = require('./adapters/http');} else if (typeof XMLHttpRequest !== 'undefined') {// 瀏覽器環境adapter = require('./adapters/xhr');}return adapter; }var defaults = {adapter: getDefaultAdapter(),/* 其他配置 */ };modules.exports = defaults;/lib/adapters/http.js與/lib/adapters/xhr.js兩個文件導出的函數都返回一個promise,具體的實現方式就不分析了。里面有很多http請求的細節,可以仔細研究。
取消請求
官方文檔中的調用方法
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.');我們進入CancelToken類,找到了CancelToken.source()方法:
// /lib/cancel/CancelTokenCancelToken.source = function source() {var cancel;var token = new CancelToken(function executor(c) {cancel = c;});return {token: token,cancel: cancel}; };可以看出,CancelToken.source().token是一個CancelToken類的實例,CancelToken.source().cancel是new CacelToken()時傳入參數(一個函數)的參數(也是個函數),通過CancelToken的構造函數可以看出:
// /lib/cancel/CancelTokenfunction CancelToken(executor) {if (typeof executor !== 'function') {throw new TypeError('executor must be a function.');}var resolvePromise;this.promise = new Promise(function promiseExecutor(resolve) {resolvePromise = resolve;});var token = this;executor(function cancel(message) {if (token.reason) {// Cancellation has already been requestedreturn;}token.reason = new Cancel(message);resolvePromise(token.reason);}); }CancelToken.source().cancel就是這個函數:
function cancel(message) {if (token.reason) {// Cancellation has already been requestedreturn;}token.reason = new Cancel(message);resolvePromise(token.reason); }CancelToken.source().token有promise和reason兩個屬性,promise 一直處于 pending狀態,reason屬性是一個Cancel類的實例,Cancel類的構造函數如下:
// /lib/cancel/Cancel.js function Cancel(message) {this.message = message; }Cancel.prototype.toString = function toString() {return 'Cancel' + (this.message ? ': ' + this.message : ''); };Cancel.prototype.__CANCEL__ = true;在源碼中,有以下幾種方式檢測是否執行了取消請求。
1 檢測config.cancelToken是否有reason屬性,如果有,將reason拋出,axios進入rejected狀態。
2 在請求過程中,執行CancelToken.source().token的promise屬性中的resolve函數,參數是CancelToken.source().token.reason,并將其拋出,promise進入rejected狀態
if (config.cancelToken) {// Handle cancellationconfig.cancelToken.promise.then(function onCanceled(cancel) {if (!request) {return;}// 取消請求request.abort();// promise進入rejectedreject(cancel);// Clean up requestrequest = null;}); }調用方法中catch接到的thrown,就是CancelToken.source().token.reason。
如果在使用axios時候,只在config中添加{cancelToken: source.token},而不調用source.cancel(),則CancelToken.source().token不會有reason屬性,CancelToken.source().token.promise也一直是pending狀態。請求不會取消。
參考
深入淺出 axios 源碼
axios源碼分析——取消請求
總結
以上是生活随笔為你收集整理的(Ajax)axios源码简析(三)——请求与取消请求的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu进行apt-get时候出现P
- 下一篇: 016 pickle