axios 學習筆記
阿新 • • 發佈:2020-10-16
axios
instance 定義
\\ 定義配置 config 和 請求前後的 interceptor function Axios(instanceConfig) { this.defaults = instanceConfig; this.interceptors = { request: new InterceptorManager(), response: new InterceptorManager() }; } \\ request 構造請求核心程式碼,返回 promise 物件 Axios.prototype.request = function request(config) { /*eslint no-param-reassign:0*/ // Allow for axios('example/url'[, config]) a la fetch API if (typeof config === 'string') { config = arguments[1] || {}; config.url = arguments[0]; } else { config = config || {}; } config = mergeConfig(this.defaults, config); // Set config.method if (config.method) { config.method = config.method.toLowerCase(); } else if (this.defaults.method) { config.method = this.defaults.method.toLowerCase(); } else { config.method = 'get'; } // Hook up interceptors middleware var chain = [dispatchRequest, undefined]; // dispatchRequest http請求 var promise = Promise.resolve(config); //執行 request 階段的 注入器,resolve接受的引數是 config this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { chain.unshift(interceptor.fulfilled, interceptor.rejected); }); // request 注入器 this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { chain.push(interceptor.fulfilled, interceptor.rejected); }); // response 注入器 while (chain.length) { promise = promise.then(chain.shift(), chain.shift()); } return promise; }; // 建立 get,post 等代理方法 // Provide aliases for supported request methods utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { /*eslint func-names:0*/ Axios.prototype[method] = function(url, config) { return this.request(mergeConfig(config || {}, { method: method, url: url, data: (config || {}).data })); }; }); utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { /*eslint func-names:0*/ Axios.prototype[method] = function(url, data, config) { return this.request(mergeConfig(config || {}, { method: method, url: url, data: data })); }; });
建立 instance
// 建立 例項方法 function createInstance(defaultConfig) { var context = new Axios(defaultConfig); var instance = bind(Axios.prototype.request, context); // Copy axios.prototype to instance utils.extend(instance, Axios.prototype, context); // Copy context to instance utils.extend(instance, context); return instance; } // 注入器使用 InterceptorManager.prototype.use = function use(fulfilled, rejected) { this.handlers.push({ fulfilled: fulfilled, rejected: rejected }); return this.handlers.length - 1; };
執行 request
- 執行流程
Promise.resolve(config) -- > interceptors.request -- >
[dispatchRequest, undefined] -- > interceptors.response
// dispatchRequest module.exports = function dispatchRequest(config) { throwIfCancellationRequested(config); // Ensure headers exist config.headers = config.headers || {}; // Transform request data config.data = transformData( config.data, config.headers, config.transformRequest ); // Flatten headers config.headers = utils.merge( config.headers.common || {}, config.headers[config.method] || {}, config.headers ); utils.forEach( ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], function cleanHeaderConfig(method) { delete config.headers[method]; } ); var adapter = config.adapter || defaults.adapter; // adapter(config) 請求後臺服務 return adapter(config).then(function onAdapterResolution(response) { throwIfCancellationRequested(config); // Transform response data response.data = transformData( response.data, response.headers, config.transformResponse ); return response; // request 注入器 resolve 引數 response }, function onAdapterRejection(reason) { if (!isCancel(reason)) { throwIfCancellationRequested(config); // Transform response data if (reason && reason.response) { reason.response.data = transformData( reason.response.data, reason.response.headers, config.transformResponse ); } } return Promise.reject(reason); }); }; // web 使用 XMLHttpRequest, node 使用 http function getDefaultAdapter() { var adapter; if (typeof XMLHttpRequest !== 'undefined') { // For browsers use XHR adapter adapter = require('./adapters/xhr'); } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') { // For node use HTTP adapter adapter = require('./adapters/http'); } return adapter; }