架构与库皆是辅助工具,原生植物为王序言:
            评注责任编辑,专业委员会以反向观念回收那时市售较为流入的js库的PCB形式
            想全盘搞清楚ajax允诺,全盘搞清楚Promise ,改写axios 库毫无疑问是最轻松的优先选择
            要想展开axios的核心理念部份改写,须要对ajax其间端统计数据初步设计,Promise 后端微各项任务,都有很大的介绍才能展开。
axios核心理念库能全力支持服务器端允诺与后端允诺,责任编辑只特别针对axios后端常用方式展开改写。axios 是甚么 是不是用
            axios 是如前所述Promise PCB了HTTTP 允诺的 库。
axios 的采用方式非常简单,能替代原生植物js 展开其间端统计数据允诺可视化。axios 导入后采用形式
形式一:透过axios 表达式传至允诺重要信息第一类axios({
                method:“get”,
                url:“url门牌号”,
                params:{key:value}
                }).then()
                axios({
                method:“post”,
                url:“url门牌号”,
                data:{key:value}
                }).then()
            
形式二:透过axios 下方式别名调用axios.get(url门牌号?key=value).then()
                axios.post(url门牌号,{key:value}).then()
            
形式三:透过内置方式实例化后调用const instance = axios.create({
                baseURL: 服务器全局默认门牌号,
                timeout: 1000,
                headers: {允诺头第一类}
                });
                instance.get(允诺门牌号,{params:{key:value}}).then()
                instance.post(允诺门牌号,{key,value}).then()
            
            axios 返回值
axios 的返回值是一个第一类,其中 data属性才是后端真正的返回统计数据{
                config: {…},
                data: {code: 0, msg: 欢迎你,李四同学,get允诺成功啦~你离后端大神更近一步啦~},
                headers: {content–length: 97, content–type: application/json; charset=utf-8},
                request:…},
                status: 200,
                statusText: “OK”
                }
            
            以上就是关于axios 基本允诺的采用形式了,特殊的方式放到后面再展开介绍,下面我们开始核心理念库的改写~
            源码分析
            axios 即是一个表达式,又是一个第一类。
            两个大层次划分:
            第一层: 生成axios 特殊的表达式/第一类,关联这个表达式和Axios类的属性及方式,并暴露这个表达式
            第二层:定义Axios 类,定义类的属性(全局配置,拦截器..),核心理念方式:request 批量定义类的原型方式 (get,post,put..)
反向回收实现axios的核心理念
            1.实现三种不同的调用形式
axios.js// 生成axios 表达式
                function createAxios() {
                // 创建一个表达式
                 const instance = function () {
                return axios调用中
                }
                // 给这个表达式添加get post 等属性 instance.get = function () {
                return get调用成功
                }
                instance.post = function () {
                return post调用成功
                }
                // 初始化方式 返回当前这个表达式 instance.create = function () {
                return createAxios();
                }
                // 返回这个表达式
                 return instance;
                }
                // 生成axios 并暴露[因为直接在 原生植物html/js 环境测试 暂时不采用模块化语法暴露]const axios = createAxios();
            
test.html <script src=“./axios.js”></script>
                <script>
                // 形式一: axios(config)
                 console.log( axios() );
                // 形式二: axios.get()
                 console.log(axios.get());
                // 方式三:实例初始化 const instance = axios.create();
                console.log( instance.post() );
                </script>
            
            问题:
            能看到 目前三种调用形式都已全力支持
            1.配置参数未传递过去 config
2.统计数据接收 .then() .catch() 还没有2.接收允诺参数,并发送允诺,返回promise
实现get允诺三种允诺形式,并返回统计数据/**
                * createAxios 生成axios 表达式/第一类 * @returns function / Object
                 */
                function createAxios() {
                // 创建一个表达式
                 const instance = function (config) {
                // 根据不同允诺类型-调用instance 第一类上的方式
                 const { method } = config;
                // 例:method==get 实现:this.get(url,config)
                 return instance[method](config)
                }
                // 给这个表达式添加get post 等属性
                 instance.get = function (config) {
                // 为了满足两种形式必须写入 url 和 config // 有config 就是透过形式1调用 没有config就是形式2/3调用
                 // 形式2/3调用没有config 须要组装一个config
                 let newConfig = {};
                if (typeof config == string) {
                //形式2 和形式3
                 //第一个参数都是url
                 //如果后面继续跟参数第一类,必是 包含params第一类统计数据
                 let arg = […arguments];
                let paramsData = arg.length > 1 ? arg[1] : {};
                newConfig = { method: get, url: config, …paramsData }
                } else {
                newConfig = { …config, method: get }
                }
                return request(newConfig)
                }
                instance.post = function () {
                return post调用成功
                }
                // 初始化方式 返回当前这个表达式
                 instance.create = function () {
                return createAxios();
                }
                // 返回这个表达式
                 return instance;
                }
                /**
                 * request 发送axios
                * @return Promise */
                function request(config) {
                 const { url, method, params, data, headers } = config;
                return new Promise((resolve, reject) => {
                // 初始化 ajax
                 let xhr = new XMLHttpRequest();
                // open send
                 if (method.toLowerCase() == get) {
                xhr.open(method, url + paramsFormat(params));
                xhr.send()
                }
                if (method == post) {
                // 默认允诺头 json
                 let header = { Content-type: application/json }
                // 设置允诺头
                 xhr.setRequestHeader({ …header, …headers })
                xhr.open(method, url);
                xhr.send()
                }
                xhr.onreadystatechange = function () {
                if (xhr.status == 200 && xhr.readyState == 4) {
                resolve(JSON.parse(xhr.responseText))
                } else if (xhr.readyState == 4) {
                reject(new Error(axios 错误))
                }
                }
                })
                }
                /**
                * paramsFormat 格式化get允诺统计数据* @params Object {key:value,key1:value1}
                * @return String ?key=value&key1=value1
                */
                function paramsFormat(params) {
                let str = ;
                //有统计数据,在展开处理
                 if (params) {
                for (key in params) {
                str += `&${key}=${params[key]}`;
                }
                str = ? + str.slice(1);
                }
                return str;
                }
                // 生成axios 并暴露[因为直接在 原生植物html/js 环境测试 暂时不采用模块化语法暴露]
                const axios = createAxios();
            
测试三种get允诺注:以下接口只是用来展开测试时采用,请勿恶意攻击服务器 //1
                 axios({
                method: get,
                url: http://115.159.153.85:8001/getTest,
                params: { name: “张三” }
                }).then(res => {
                console.log(res);
                })
                //2
                 axios.get(http://115.159.153.85:8001/getTest?name=李四).then(res => {
                console.log(res);
                })
                //3
                 //这里的初始化 允诺头、拦截器参数这部份还未完善
                 let instance = axios.create();
                instance.get(http://115.159.153.85:8001/getTest, { params: { name: 黄四郎 } }).then(res => {
                console.log(res);
                })
            
            
            3.完善request 表达式,全力支持post允诺
            /**
                 * createAxios 生成axios 表达式/第一类
                 * @returns function / Object
                 */
                function createAxios() {
                // 创建一个表达式 const instance = function (config) {
                // 根据不同允诺类型-调用instance 第一类上的方式
                 const { method } = config;
                // 例:method==get 实现:this.get(url,config) return instance[method](config)
                }
                // 给这个表达式添加get post 等属性
                 instance.get = function (config) {
                // 为了满足两种形式必须写入 url 和 config
                 // 有config 就是透过形式1调用 没有config就是形式2/3调用
                 // 形式2/3调用没有config 须要组装一个config let newConfig = {};
                if (typeof config == string) {
                //形式2 和形式3
                 //第一个参数都是url
                 //如果后面继续跟参数第一类,必是 包含params第一类统计数据
                 let arg = […arguments];
                let paramsData = arg.length > 1 ? arg[1] : {};
                newConfig = { method: get, url: config, …paramsData }
                } else {
                newConfig = { …config, method: get }
                }
                return request(newConfig)
                }
                instance.post = function (config) {
                // 重新组装config 思路与get允诺一致 //暂时不考虑 config.headers 允诺头相关
                 let newConfig = {};
                if (typeof config == string) {
                //2/3
                 let arg = […arguments];
                let data = arg.length > 1 ? arg[1] : {};
                newConfig = { method: post, url: config, data }
                } else {
                //1
                 newConfig = { …config, method: post }
                }
                return request(newConfig);
                }
                // 初始化方式 返回当前这个表达式
                 instance.create = function () {
                return createAxios();
                }
                // 返回这个表达式
                 return instance;
                }
                /**
                 * request 发送axios
                 * @return Promise
                 */
                function request(config) {
                 const { url, method, params, data, headers } = config;
                return new Promise((resolve, reject) => {
                // 初始化 ajax
                 let xhr = new XMLHttpRequest();
                // open send
                 if (method.toLowerCase() == get) {
                xhr.open(method, url + paramsFormat(params));
                xhr.send()
                }
                if (method == post) {
                xhr.open(method, url);
                xhr.setRequestHeader(Content-Type, application/json);
                // 默认允诺头 json ,后续透过其他表达式统一处理 允诺头和参数
                 let sendData = JSON.stringify(data);
                xhr.send(sendData)
                }
                xhr.onreadystatechange = function () {
                if (xhr.status == 200 && xhr.readyState == 4) {
                resolve(JSON.parse(xhr.responseText))
                } else if (xhr.readyState == 4) {
                reject(new Error(axios 错误))
                }
                }
                })
                }
                /**
                * paramsFormat 格式化get允诺统计数据* @params Object {key:value,key1:value1}
                * @return String ?key=value&key1=value1
                */
                function paramsFormat(params) {
                let str = ;
                //有统计数据,在展开处理
                 if (params) {
                for (key in params) {
                str += `&${key}=${params[key]}`;
                }
                str = ? + str.slice(1);
                }
                return str;
                }
                // 生成axios 并暴露[因为直接在 原生植物html/js 环境测试 暂时不采用模块化语法暴露]
                const axios = createAxios();
            
测试 //1
                 axios({
                method: post,
                url: http://115.159.153.85:8001/postTest,
                data: { name: “张三1” }
                }).then(res => {
                console.log(res);
                })
                //2
                 axios.post(http://115.159.153.85:8001/postTest, { name: “张三2” }).then(res => {
                console.log(res);
                })
                //3
                 const instance = axios.create();
                instance.post(http://115.159.153.85:8001/postTest, { name: 张三3 }).then(res => {
                console.log(res);
                })
            
            
            剩余问题:
            1.透过axios.create() 方式初始化axios时 全力支持 headers baseUrl timeOut 等属性 的设置
            2.不同的允诺头 的允诺参数的格式不同
3.目前只全力支持了 get 允诺 post 允诺 ,应该全力支持更多的允诺形式: put patch delete …按照axios 源码思路复现
            1.评注源码-回收axios 源码
源码门牌号: https://github.com/axios/axios/tree/v1.x/lib/core
            
            2.源码注释
            Axios.js定义Axios核心理念库,实现所有的请求形式,requestajax 核心理念方式的PCB
https://github.com/axios/axios/blob/v1.x/lib/core/Axios.js
            use strict;
                import utils from ./../utils.js;
                import buildURL from ../helpers/buildURL.js;
                import InterceptorManager from ./InterceptorManager.js;
                import dispatchRequest from ./dispatchRequest.js;
                import mergeConfig from ./mergeConfig.js;
                import buildFullPath from ./buildFullPath.js;
                import validator from ../helpers/validator.js;
                import AxiosHeaders from ./AxiosHeaders.js;
                const validators = validator.validators;
                /**
                 * Axios 类的创建
                配置的参数第一类{headers:….} */
                class Axios {
                constructor(instanceConfig) {
                 this.defaults = instanceConfig;
                // 这里是拦截器的初始化,放到之后实例第一类的属性上【允诺拦截器和响应拦截器】
                 this.interceptors = {
                request: new InterceptorManager(),
                response: new InterceptorManager()
                };
                }
                /**
                * request 方式是PCB了ajax 允诺的核心理念方式,主要PCB的是关于ajax的允诺头,参数格式化,各种允诺方式的原型方式挂载 *
                 * @param {String|Object} configOrUrl
                * 有的调用方式,须要传递两个统计数据,第一个是url 和二个参数是一个第一类【允诺传递的统计数据,允诺头等等,对应不同的调用形式】 * @param {?Object} config
                 *
                * 返回一个Promise 状态机,这个Promise就是能在 调用时写 .then() .catch()接收统计数据的原因 * @returns {Promise}
                 */
                request(configOrUrl, config) {
                /**处理不同调佣形式传递的统计数据,只传递了一个url过来的重新组装一个config 第一类,传递了第2个参数,config第一类加一个url属性 */
                if (typeof configOrUrl === string) {
                config = config || {};
                config.url = configOrUrl;
                } else {
                config = configOrUrl || {};
                }
                /** 将config 第一类展开格式化处理:和全局默认配置展开合并,如果都有允诺头这种,须要做合并处理 */
                config = mergeConfig(this.defaults, config);
                const {transitional, paramsSerializer} = config;
                if (transitional !== undefined) {
                validator.assertOptions(transitional, {
                silentJSONParsing: validators.transitional(validators.boolean),
                forcedJSONParsing: validators.transitional(validators.boolean),
                clarifyTimeoutError: validators.transitional(validators.boolean)
                }, false);
                }
                if (paramsSerializer !== undefined) {
                validator.assertOptions(paramsSerializer, {
                encode: validators.function,
                serialize: validators.function
                }, true);
                }
                // 处理多种调用形式,axios.get() axios({method:get}) 重新组装config 添加method属性
                 config.method = (config.method || this.defaults.method || get).toLowerCase();
                // Flatten headers
                 const defaultHeaders = config.headers && utils.merge(
                config.headers.common,
                config.headers[config.method]
                );
                // 透过定义好的所有的允诺形式,匹配调用时传递进来的方式 重新组装 config的 method属性 defaultHeaders && utils.forEach(
                [delete, get, head, post, put, patch, common],
                function cleanHeaderConfig(method) {
                delete config.headers[method];
                }
                );
                config.headers = new AxiosHeaders(config.headers, defaultHeaders);
                // 拿到所有的允诺拦截器 和响应拦截器的表达式代码
                 const requestInterceptorChain = [];
                let synchronousRequestInterceptors = true;
                this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
                if (typeof interceptor.runWhen === function && interceptor.runWhen(config) === false) {
                return;
                }
                synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
                requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
                });
                const responseInterceptorChain = [];
                this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
                responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
                });
                let promise;
                let i = 0;
                let len;
                //拦截器验证,给一个promise透过了拦截器之后 在展开下一步
                 if (!synchronousRequestInterceptors) {
                const chain = [dispatchRequest.bind(this), undefined];
                chain.unshift.apply(chain, requestInterceptorChain);
                chain.push.apply(chain, responseInterceptorChain);
                len = chain.length;
                promise = Promise.resolve(config);
                while (i < len) {
                promise = promise.then(chain[i++], chain[i++]);
                }
                return promise;
                }
                len = requestInterceptorChain.length;
                let newConfig = config;
                i = 0;
                while (i < len) {
                const onFulfilled = requestInterceptorChain[i++];
                const onRejected = requestInterceptorChain[i++];
                try {
                newConfig = onFulfilled(newConfig);
                } catch (error) {
                onRejected.call(this, error);
                break;
                }
                }
                try {
                promise = dispatchRequest.call(this, newConfig);
                } catch (error) {
                return Promise.reject(error);
                }
                i = 0;
                len = responseInterceptorChain.length;
                while (i < len) {
                promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]);
                }
                return promise;
                }
                // 再次特别针对config.url展开格式化(防止参数里面有特殊字符和中文汉字等等) getUri(config) {
                config = mergeConfig(this.defaults, config);
                const fullPath = buildFullPath(config.baseURL, config.url);
                return buildURL(fullPath, config.params, config.paramsSerializer);
                }
                }
                // 全力支持 axios.get axios.delete 形式的调用,将这个允诺形式全部挂载到 原型方式,并特别针对这四个方式展开允诺头的处理
                
                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,
                url,
                data: (config || {}).data
                }));
                };
                });
                // 全力支持 axios.post axios.put 形式的调用,将这个允诺形式全部挂载到 原型方式,并特别针对这四个方式展开允诺头的处理
                utils.forEach([post, put, patch], function forEachMethodWithData(method) {
                //PCB表达式 实现 允诺头 相关的属性的格式化
                 function generateHTTPMethod(isForm) {
                return function httpMethod(url, data, config) {
                return this.request(mergeConfig(config || {}, {
                method,
                headers: isForm ? {
                Content-Type: multipart/form-data
                } : {},
                url,
                data
                }));
                };
                }
                //向Axios 类的原型上挂载 所有的方式 get put patch delete get head options Axios.prototype[method] = generateHTTPMethod();
                Axios.prototype[method + Form] = generateHTTPMethod(true);
                });
                //暴露Axios 类,透过另外一个js文件接收,并实例化
                export default Axios;