前戏
在正式开始 axios 讲解前, 让我们先想想, 如何对现有的 $.ajax 进行简单的封装, 就可以直接使用原声 Promise 了?
- let axios = function(config){
- return new Promise((res, rej) => {
- // 发送 ajax 请求, 一般使用 $.ajax()
- ajax({
- ...config,
- success(data){
- res(data);
- },
- error(e){
- rej(e);
- }
- })
- })
- }
然后就可以 axios(...).then().catch() 的使用了.
通过上面简单代码, 我们就已经清楚了 axios 基本的实现原理:
内部通过 Promise 对 XHR 对象及其事件进行封装,
然后外部就可以通过操作 Promise 的方式进行异步处理了.
是不是很简单, 那接下来就开始我们正式的讲解吧
为 url,data,headers 添加统一处理方法
- /**
- * 2, 为 url,data,headers 添加统一处理方法
- */
- let axios = function(config) {
- return new Promise((res, rej) => {
- // 为 url,data,headers 添加统一处理方法
- // (此处只为展示大概架构, 暂时不必关心方法的实现, 下面会做详细介绍)
- let { url, method, data, params, headers } = config;
- url = buildURL(combineURLs(config.baseURL, url), params);
- headers = merge(headers.common, headers);
- data = transformData(data, headers);
- // 发送 ajax 请求, 一般使用 $.ajax()
- ajax({
- ...config,
- url,
- data,
- headers,
- success(data) {
- res(data);
- },
- error(e) {
- rej(e);
- }
- })
- })
- }
放弃 ajax 方法, 对原生 XHR 进行简单封装
- /**
- * 3, 放弃 ajax 方法, 对原生 XHR 进行简单封装
- */
- let axios = function (config) {
- // 默认配置项
- let defaultConfig = {
- method: 'get',
- responseType: 'json',
- timeout: 0,
- }
- return new Promise((res, rej) => {
- config = merge(defaultConfig, config);
- // 为 url,data,headers 添加统一处理方法
- let { url, method, data, params, headers } = config;
- url = buildURL(combineURLs(config.baseURL, url), params);
- headers = merge(headers.common, headers);
- data = transformData(data, headers);
- // 创建 xhr 实例
- var xhr = new XMLHttpRequest();
- xhr.open(method, url);
- xhr.responseType = config.responseType;
- xhr.timeout = config.timeout;
- request.addEventListener('progress', config.onDownloadProgress);
- xhr.onload = function () {
- // 先要判断 xhr.status 逻辑
- res(xhr.response)
- };
- xhr.onerror = function () {
- rej('Network Error')
- };
- xhr.ontimeout = function handleTimeout() {
- rej('timeout');
- };
- xhr.send(data);
- })
- }
改用 class 来实现一个简单的 axios
- /**
- * 4, 改用 class 来实现一个简单的 axios
- */
- class Axios {
- constructor(instanceConfig){
- this.defaults = instanceConfig;
- }
- request(config){
- this.config = {
- ...this.defaults,
- ...config,
- }
- this.dispatchRequest();
- }
- dispatchRequest(){
- // 为 url,data,headers 添加统一处理方法
- let { url, method, data, params, headers } = this.config;
- url = buildURL(combineURLs(config.baseURL, url), params);
- headers = merge(headers.common, headers);
- data = transformData(data, headers);
- // 创建 xhr 实例
- var xhr = new XMLHttpRequest();
- xhr.open(method, url);
- xhr.responseType = config.responseType;
- xhr.timeout = config.timeout;
- request.addEventListener('progress', config.onDownloadProgress);
- xhr.onload = function () {
- // 先要判断 xhr.status 逻辑
- res(xhr.response)
- };
- xhr.onerror = function () {
- rej('Network Error')
- };
- xhr.ontimeout = function handleTimeout() {
- rej('timeout');
- };
- xhr.send(data);
- }
- }
- // 默认配置项
- let defaultConfig = {
- method: 'get',
- responseType: 'json',
- timeout: 0,
- }
- // 创建 axios 实例, 使 axios 具有 axios() 直接调用方式和 axios.request() 调用方式
- function createInstance(defaultConfig){
- let context = new Axios(defaultConfig);
- let instance = Axios.prototype.request.bind(context);
- extend(instance, Axios.prototype, context);
- extend(instance, context);
- }
- let axios = createInstance(defaultConfig);
添加 get,post,put 等简写用法
- /**
- * 5, 添加 get,post,put 等简写用法
- */
- class Axios {
- constructor(instanceConfig) {
- this.defaults = instanceConfig;
- }
- request(config) {
- this.config = {
- ...this.defaults,
- ...config,
- }
- this.dispatchRequest();
- }
- dispatchRequest() {
- // 为 url,data,headers 添加统一处理方法
- let { url, method, data, params, headers } = this.config;
- url = buildURL(combineURLs(config.baseURL, url), params);
- headers = merge(headers.common, headers);
- data = transformData(data, headers);
- // 创建 xhr 实例
- var xhr = new XMLHttpRequest();
- xhr.open(method, url);
- xhr.responseType = config.responseType;
- xhr.timeout = config.timeout;
- request.addEventListener('progress', config.onDownloadProgress);
- xhr.onload = function () {
- // 先要判断 xhr.status 逻辑
- res(xhr.response)
- };
- xhr.onerror = function () {
- rej('Network Error')
- };
- xhr.ontimeout = function handleTimeout() {
- rej('timeout');
- };
- xhr.send(data);
- }
- }
- let noDataMethods = ['delete', 'get', 'head', 'options'];
- let hasDataMethods = ['post', 'put', 'patch'];
- for (const method of noDataMethods) {
- Axios.prototype[method] = function (url, config = {}){
- return this.request({
- ...config,
- method: method,
- url: url,
- });
- }
- }
- for (const method of hasDataMethods) {
- Axios.prototype[method] = function (url, data, config = {}) {
- return this.request({
- ...config,
- method: method,
- url: url,
- data,
- });
- }
- }
- // 默认配置项
- let defaultConfig = {
- method: 'get',
- responseType: 'json',
- timeout: 0,
- }
- // 创建 axios 实例, 使 axios 具有 axios() 直接调用方式和 axios.request() 调用方式
- function createInstance(defaultConfig) {
- let context = new Axios(defaultConfig);
- let instance = Axios.prototype.request.bind(context);
- extend(instance, Axios.prototype, context);
- extend(instance, context);
- }
- let axios = createInstance(defaultConfig);
增加拦截功能, 在请求前修改配置和数据, 在请求后修改返回结果
- /**
- * 6, 增加拦截功能, 在请求前修改配置和数据, 在请求后修改返回结果
- */
- class Axios {
- constructor(instanceConfig) {
- this.defaults = instanceConfig;
- }
- request(config) {
- this.config = {
- ...this.defaults,
- ...config,
- }
- var chain = [dispatchRequest, undefined];
- var promise = Promise.resolve(config);
- }
- dispatchRequest(config) {
- // 为 url,data,headers 添加统一处理方法
- let { url, method, data, params, headers } = config;
- url = buildURL(combineURLs(config.baseURL, url), params);
- headers = merge(headers.common, headers);
- data = transformData(data, headers);
- // 创建 xhr 实例
- var xhr = new XMLHttpRequest();
- xhr.open(method, url);
- xhr.responseType = config.responseType;
- xhr.timeout = config.timeout;
- request.addEventListener('progress', config.onDownloadProgress);
- xhr.onload = function () {
- // 先要判断 xhr.status 逻辑
- res(xhr.response)
- };
- xhr.onerror = function () {
- rej('Network Error')
- };
- xhr.ontimeout = function handleTimeout() {
- rej('timeout');
- };
- xhr.send(data);
- }
- }
- let noDataMethods = ['delete', 'get', 'head', 'options'];
- let hasDataMethods = ['post', 'put', 'patch'];
- for (const method of noDataMethods) {
- Axios.prototype[method] = function (url, config = {}) {
- return this.request({
- ...config,
- method: method,
- url: url,
- });
- }
- }
- for (const method of hasDataMethods) {
- Axios.prototype[method] = function (url, data, config = {}) {
- return this.request({
- ...config,
- method: method,
- url: url,
- data,
- });
- }
- }
- // 默认配置项
- let defaultConfig = {
- method: 'get',
- responseType: 'json',
- timeout: 0,
- }
- // 创建 axios 实例, 使 axios 具有 axios() 直接调用方式和 axios.request() 调用方式
- function createInstance(defaultConfig) {
- let context = new Axios(defaultConfig);
- let instance = Axios.prototype.request.bind(context);
- extend(instance, Axios.prototype, context);
- extend(instance, context);
- }
- let axios = createInstance(defaultConfig);
- // 其他:
- // 撤销请求 abort
- // 添加 xsrf header
未完待续...
来源: https://www.cnblogs.com/wwwweb/p/axios.html