From f4d61c7af70fcdfafea5e63365034ec9537ff1db Mon Sep 17 00:00:00 2001 From: "954270063@qq.com" <954270063@qq.com> Date: Fri, 17 Apr 2020 23:20:34 +0800 Subject: [PATCH] =?UTF-8?q?:construction:=20=E7=BC=96=E5=86=99=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E4=B8=AD...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 196 ++++++++++++++++++++++++--------- src/axios.ts | 8 +- src/core/requestAdapter.ts | 3 +- src/helper/mergeConfig.ts | 153 +++++++++++++++++-------- src/helper/transformRequest.ts | 2 +- src/types.ts | 7 +- 6 files changed, 263 insertions(+), 106 deletions(-) diff --git a/README.md b/README.md index 3f8dd78..fd52bb1 100644 --- a/README.md +++ b/README.md @@ -33,78 +33,176 @@ npm i axios-miniprogram ## API -可以通过将相关配置传递给 `axios` 来发送请求。 +可以通过将相关配置传递给`axios`来发送请求。 ### `axios(config)` ```typescript - // 默认发送 GET 请求 - axios({ - url: '/test', - params: { test: 1 } - }); +// 默认发送 GET 请求 +axios({ + url: '/test', + params: { test: 1 } +}); - // 发送 POST 请求 - axios({ - url: '/test', - method: 'post', - data: { test: 1 } - }); +// 发送 POST 请求 +axios({ + url: '/test', + method: 'post', + data: { test: 1 } +}); ``` -也可以通过直接把 `url` 传给 `axios` 来发送请求。 +也可以通过直接把`url`传给`axios`来发送请求。 ### `axios(url, config?)` ```typescript - // 默认发送 GET 请求 - axios('/test/xxx'); +// 默认发送 GET 请求 +axios('/test/xxx'); - // 发送 POST 请求 - axios('/test/xxx', { method: 'post' }); +// 发送 POST 请求 +axios('/test/xxx', { method: 'post' }); ``` -也可以使用请求方法别名来简化请求 +还可以使用请求方法别名来简化请求 -##### axios.request(config) - -##### axios.options(url, config?) -##### axios.trace(url, config?) -##### axios.connect(url, config?) - -##### axios.get(url, params?, config?) -##### axios.head(url, params?, config?) -##### axios.delete(url, params?, config?) - -##### axios.post(url, data?, config?) -##### axios.put(url, data?, config?) +* ##### axios.request(config) +* ##### axios.options(url, config?) +* ##### axios.trace(url, config?) +* ##### axios.connect(url, config?) +* ##### axios.get(url, params?, config?) +* ##### axios.head(url, params?, config?) +* ##### axios.delete(url, params?, config?) +* ##### axios.post(url, data?, config?) +* ##### axios.put(url, data?, config?) 常用例子,其他同理: ```typescript - // 发送 GET 请求 - axios.get('/test'); +// 发送 GET 请求 +axios.get('/test'); - // 携带参数 - axios.get('/test', { test: 1 }); +// 携带参数 +axios.get('/test', { test: 1 }); - // 携带额外配置 - axios.get('/test', { test: 1 }, { - headers: { - 'content-type': 'application/json; charset=utf-8' +// 携带额外配置 +axios.get('/test', { test: 1 }, { + headers: { + 'Content-Type': 'application/json; charset=utf-8' + } +}); + +// 发送 POST 请求 +axios.post('/test'); + +// 携带数据 +axios.post('/test', { test: 1 }); + +// 携带额外配置 +axios.post('/test', { test: 1 }, { + headers: { + 'Content-Type': 'application/json; charset=utf-8' + } +}); +``` + +### 默认配置 + +##### 全局默认配置`axios.defaults` + +```typescript +axios.defaults.baseURL = 'https://www.xxx.com'; +axios.defaults.headers.common['Accept'] = 'application/json, test/plain, */*'; +axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; +``` + +##### 自定义实例默认配置 + +```typescript +// 可以创建时传入 +const instance = axios.create({ + baseURL: 'https://www.xxx.com', + headers: { + common: { + 'Accept': 'application/json, test/plain, */*' + }, + post: { + 'Content-Type': 'application/x-www-form-urlencoded' } - }); + } +}); - // 发送 POST 请求 - axios.post('/test'); +// 也可以创建后修改 +instance.defaults.baseURL = 'https://www.xxx.com'; +instance.defaults.headers.common['Accept'] = 'application/json, test/plain, */*'; +instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; +``` - // 携带数据 - axios.post('/test', { test: 1 }); +##### 配置优先顺序 - // 携带额外配置 - axios.post('/test', { test: 1 }, { - headers: { - 'content-type': 'application/json; charset=utf-8' - } - }); +发送请求时,会使用默认配置`defaults`和自定义配置`config` 合并出请求配置,具体合并策略参考 [mergeConfig.ts](https://github.com/early-autumn/axios-miniprogram/blob/master/src/helper/mergeConfig.ts),多数情况下,后者优先于前者 + + + +### `axios.getUri(config)` + +根据传入的配置生成完整的`URL`。 + +```typescript +axios.defaults.baseURL = 'https://www.xxx.com'; + +// uri === 'https://www.xxx.com/test?id=1' +const uri = axios.getUri({ + url: '/test', + params: { id: 1 } +}); + +// uri2 === 'https://www.yyy.com/test?id=1' +const uri2 = axios.getUri({ + baseURL: 'https://www.yyy.com', + url: '/test', + params: { id: 1 } +}); +``` + +### `axios.create(config)` + +创建一个`自定义实例`,传入的自定义配置会和`axios`的默认配置合并成`自定义实例`的默认配置。 + +`自定义实例`拥有和`axios`相同的调用方式和请求方法别名。 + +```typescript +axios.defaults.baseURL = 'https://www.xxx.com'; + +const instance = axios.create({ + params: { + id: 1 + } +}); + +// 最终请求的 URL 是这样的 => https://www.xxx.com/test?id=1 +// https://www.xxx.com 来自 axios.defaults.baseURL +// /test 来自传入的 '/test' +// id=1 来自 instance.defaults.params +instance('/test'); +instance.get('/test'); +``` + +### `axios.Axios` + +`axios.Axios`是一个类,其实`axios`就是`axios.Axios`类的实例改造而来的`axios.create(config)`创建的也是`axios.Axios`的实例。 + +直接实例化`axios.Axios`可以得到一个`纯净的实例`,不能当函数调用,传入的自定义配置就是`纯净的实例`的默认配置,而不会像`axios.create(config)`一样去合并`axios`中的默认配置。 + +```typescript +axios.defaults.baseURL = 'https://www.xxx.com'; + +const instance = new axios.Axios({ + params: { value: '零污染' } +}); + +// 最终请求的 URL 是这样的 => /test?value=零污染 +// /test 来自传入的 '/test' +// value=零污染 来自 instance.defaults.params +instance.get('/test'); ``` \ No newline at end of file diff --git a/src/axios.ts b/src/axios.ts index 56a57b6..5673c4c 100644 --- a/src/axios.ts +++ b/src/axios.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-15 12:45:18 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-17 09:42:16 + * @LastEditTime: 2020-04-17 21:49:05 */ import { AxiosRequestConfig, Data, AxiosResponse, AxiosBaseInstance, AxiosInstance } from './types'; import Axios from './core/Axios'; @@ -62,14 +62,14 @@ function createInstance(config: AxiosRequestConfig): AxiosInstance { */ const axios = createInstance(defaults); -// 添加 Axios 类 -axios.Axios = Axios; - // 添加 create 工厂方法 axios.create = function create(config: AxiosRequestConfig): AxiosBaseInstance { return createInstance(mergeConfig(axios.defaults, config)); }; +// 添加 Axios 类 +axios.Axios = Axios; + // 添加取消相关 axios.Cancel = Cancel; axios.CancelToken = CancelToken; diff --git a/src/core/requestAdapter.ts b/src/core/requestAdapter.ts index 467f22c..a6cbad4 100644 --- a/src/core/requestAdapter.ts +++ b/src/core/requestAdapter.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-16 00:48:45 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-17 16:23:41 + * @LastEditTime: 2020-04-17 22:18:07 */ import { AxiosRequestConfig, AxiosResponse, PlatformResponse } from '../types'; @@ -61,7 +61,6 @@ export default function requestAdapter(config: AxiosRequestConfig): Promise { + if (config1[key] !== undefined) { + config[key] = config1[key] as any; + } + }); +} - const keys1: ['url', 'data'] = ['url', 'data']; - const keys2: ['headers', 'params'] = ['headers', 'params']; - const keys3: [ - 'adapter', - 'baseURL', - 'method', - 'dataType', - 'responseType', - 'timeout', - 'enableHttp2', - 'enableQuic', - 'enableCache', - 'cancelToken' - ] = [ - 'adapter', - 'baseURL', - 'method', - 'dataType', - 'responseType', - 'timeout', - 'enableHttp2', - 'enableQuic', - 'enableCache', - 'cancelToken', - ]; - - // 只取 config2 中的值 - keys1.forEach((key) => { +/** + * 只取 config2 中的配置 + * + * @param keys + * @param config + * @param config2 + */ +function onlyFromConfig2(keys: ['url', 'method', 'data'], config: AxiosRequestConfig, config2: AxiosRequestConfig) { + keys.forEach((key) => { if (config2[key] !== undefined) { config[key] = config2[key] as any; } }); +} - // 深度合并 - keys2.forEach((key) => { +/** + * 优先取 config2 中的配置 + * + * @param keys + * @param config + * @param config1 + * @param config2 + */ +function priorityFromConfig2( + keys: [ + 'baseURL', + 'method', + 'transformRequest', + 'transformResponse', + 'validateStatus', + 'paramsSerializer', + 'cancelToken', + 'dataType', + 'responseType', + 'timeout', + 'enableHttp2', + 'enableQuic', + 'enableCache', + 'sslVerify' + ], + config: AxiosRequestConfig, + config1: AxiosRequestConfig, + config2: AxiosRequestConfig +) { + keys.forEach((key) => { + if (config2[key] !== undefined) { + config[key] = config2[key] as any; + } else if (config1[key] !== undefined) { + config[key] = config1[key] as any; + } + }); +} + +/** + * 深度合并配置 + * + * @param keys + * @param config + * @param config1 + * @param config2 + */ +function deepMergeConfig( + keys: ['headers', 'params'], + config: AxiosRequestConfig, + config1: AxiosRequestConfig, + config2: AxiosRequestConfig +) { + keys.forEach((key) => { if (isPlainObject(config2[key])) { config[key] = deepMerge(config1[key] as any, config2[key] as any); } else if (config2[key] !== undefined) { @@ -61,15 +100,41 @@ export default function mergeConfig(config1: AxiosRequestConfig, config2: AxiosR config[key] = config1[key]; } }); +} - // 优先取 config2 中的配置 - keys3.forEach((key) => { - if (config2[key] !== undefined) { - config[key] = config2[key] as any; - } else if (config1[key] !== undefined) { - config[key] = config1[key] as any; - } - }); +/** + * 合并配置 + * + * @param config1 配置 1 + * @param config2 配置 2 + */ +export default function mergeConfig(config1: AxiosRequestConfig, config2: AxiosRequestConfig): AxiosRequestConfig { + const config: AxiosRequestConfig = {}; + + onlyFromConfig1(['adapter'], config, config1); + onlyFromConfig2(['url', 'method', 'data'], config, config2); + priorityFromConfig2( + [ + 'baseURL', + 'method', + 'transformRequest', + 'transformResponse', + 'validateStatus', + 'paramsSerializer', + 'cancelToken', + 'dataType', + 'responseType', + 'timeout', + 'enableHttp2', + 'enableQuic', + 'enableCache', + 'sslVerify', + ], + config, + config1, + config2 + ); + deepMergeConfig(['headers', 'params'], config, config1, config2); return config; } diff --git a/src/helper/transformRequest.ts b/src/helper/transformRequest.ts index 5cca3a6..306a7b4 100644 --- a/src/helper/transformRequest.ts +++ b/src/helper/transformRequest.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-17 15:05:43 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-17 15:20:10 + * @LastEditTime: 2020-04-17 22:22:50 */ import { Method, AxiosRequestConfig, PlatformRequestConfig } from '../types'; import transformURL from './transformURL'; diff --git a/src/types.ts b/src/types.ts index 97148dd..c76a59b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-13 15:23:53 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-17 19:13:21 + * @LastEditTime: 2020-04-17 22:22:16 */ import 'miniprogram-api-typings'; @@ -268,11 +268,6 @@ export interface PlatformRequestConfig extends AxiosRequestConfig { * 失败的响应函数 */ fail?: (err: any) => void; - - /** - * 无条件执行的响应函数 - */ - complete?: undefined; } /**