From 8d21d89dc8acdc669d8978cd3aab10bb19ac58ce Mon Sep 17 00:00:00 2001 From: early-autumn <954270063@qq.com> Date: Fri, 24 Apr 2020 09:24:43 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/launch.json | 21 ++++++++ package.json | 4 +- src/adaptive.ts | 22 ++++---- src/axios.ts | 26 ++++++---- src/cancel/Cancel.ts | 11 ++-- src/cancel/isCancel.ts | 6 +-- src/core/Axios.ts | 22 +++----- src/core/InterceptorManager.ts | 11 ++-- src/core/createError.ts | 31 +++--------- src/core/mergeConfig.ts | 93 +++++++++++++++++----------------- src/core/transformData.ts | 4 +- src/core/transformRequest.ts | 45 ++++++---------- src/core/transformResponse.ts | 4 +- src/helpers/utils.ts | 2 +- src/types.ts | 55 +++----------------- 15 files changed, 150 insertions(+), 207 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..1e7293e --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "name": "vscode-jest-tests", + "request": "launch", + "args": [ + "--runInBand" + ], + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "program": "${workspaceFolder}/node_modules/jest/bin/jest" + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index 5fc4c57..f8584d8 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,9 @@ }, "keywords": [ "axios", - "miniprogram" + "miniprogram", + "request", + "promise" ], "author": "early-autumn", "license": "MIT", diff --git a/src/adaptive.ts b/src/adaptive.ts index d5b6ee6..7efdf36 100644 --- a/src/adaptive.ts +++ b/src/adaptive.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-17 12:18:25 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-22 13:24:28 + * @LastEditTime: 2020-04-23 10:53:50 */ import { Adapter, Platform } from './types'; @@ -19,24 +19,24 @@ declare let tt: Platform; // QQ 小程序 declare let qq: Platform; -const stack = [ - () => uni.request, - () => wx.request, - () => my.request, - () => swan.request, - () => tt.request, - () => qq.request, -]; - /** * 自适应当前平台 */ function adaptive(): Adapter | undefined { + const stack = [ + () => uni.request, + () => wx.request, + () => my.request, + () => swan.request, + () => tt.request, + () => qq.request, + ]; + let adapter: Adapter | undefined; while (stack.length !== 0 && adapter === undefined) { try { - adapter = (stack.shift() as () => Adapter | undefined)(); + adapter = stack.shift()?.(); } catch (err) {} } diff --git a/src/axios.ts b/src/axios.ts index 8d1c9a5..9519c77 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-23 10:44:18 + * @LastEditTime: 2020-04-24 09:16:56 */ import { AxiosRequestConfig, Data, AxiosResponse, AxiosBaseInstance, AxiosInstance } from './types'; import Axios from './core/Axios'; @@ -16,8 +16,8 @@ import defaults from './defaults'; * * 返回一个 Axios 实例增强 */ -function createInstance(config: AxiosRequestConfig): AxiosInstance { - const instance = new Axios(config); +function createInstance(defaults: AxiosRequestConfig = {}): AxiosInstance { + const instance = new Axios(defaults); /** * 支持重载的 axios 函数 @@ -26,18 +26,16 @@ function createInstance(config: AxiosRequestConfig): AxiosInstance { url: AxiosRequestConfig | string, config: AxiosRequestConfig = {} ): Promise> { - let requestConfig: AxiosRequestConfig; - // 调用方式一处理请求配置 if (typeof url !== 'string') { - requestConfig = url; + config = url; } // 调用方式二处理请求配置 else { - requestConfig = { ...config, url }; + config = { ...config, url }; } - return instance.request(requestConfig); + return instance.request(config); } // instance 的属性合并到 axios 函数中 @@ -54,8 +52,8 @@ function createInstance(config: AxiosRequestConfig): AxiosInstance { const axios = createInstance(defaults); // 添加 create 工厂方法 -axios.create = function create(config: AxiosRequestConfig = {}): AxiosBaseInstance { - return createInstance(mergeConfig(axios.defaults, config)); +axios.create = function create(defaults: AxiosRequestConfig = {}): AxiosBaseInstance { + return createInstance(mergeConfig(axios.defaults, defaults)); }; // 添加 Axios 类 @@ -68,3 +66,11 @@ axios.CancelToken = CancelToken; axios.isCancel = isCancel; export default axios; + +export type En = T extends U ? never : T; + +export type Enn = En; + +export type Eni = T extends U ? T : never; + +export type Enni = Eni; diff --git a/src/cancel/Cancel.ts b/src/cancel/Cancel.ts index 8afcf4c..99bbb2f 100644 --- a/src/cancel/Cancel.ts +++ b/src/cancel/Cancel.ts @@ -2,16 +2,15 @@ * @Author: early-autumn * @Date: 2020-04-13 21:14:53 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-22 17:38:43 + * @LastEditTime: 2020-04-23 20:56:34 */ import { Cancel } from '../types'; export default class CancelStatic implements Cancel { - public message?: string; - - constructor(message?: string) { - this.message = message; - } + /** + * @param message 取消信息 + */ + constructor(public message?: string) {} public toString() { const message = this.message ? `: ${this.message}` : ''; diff --git a/src/cancel/isCancel.ts b/src/cancel/isCancel.ts index e7a7ee0..fcde5ce 100644 --- a/src/cancel/isCancel.ts +++ b/src/cancel/isCancel.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-14 09:23:25 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-20 15:15:27 + * @LastEditTime: 2020-04-23 22:44:43 */ import Cancel from './Cancel'; @@ -11,6 +11,6 @@ import Cancel from './Cancel'; * * @param value 判断的值 */ -export default function isCancel(value: any): boolean { - return !!value && value instanceof Cancel; +export default function isCancel(value: any): value is Cancel { + return value instanceof Cancel; } diff --git a/src/core/Axios.ts b/src/core/Axios.ts index 4f3fc49..2362802 100644 --- a/src/core/Axios.ts +++ b/src/core/Axios.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-13 18:00:27 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-23 10:12:56 + * @LastEditTime: 2020-04-23 23:43:00 */ import { Method, Params, Data, Interceptors, AxiosRequestConfig, AxiosResponse, Axios } from '../types'; import buildURL from '../helpers/buildURL'; @@ -11,26 +11,18 @@ import InterceptorManager from './InterceptorManager'; import dispatchRequest from './dispatchRequest'; export default class AxiosStatic implements Axios { - /** - * 默认配置 - */ - public defaults: AxiosRequestConfig; - /** * Axios 拦截器 */ - public interceptors: Interceptors; + public interceptors: Interceptors = { + request: new InterceptorManager(), + response: new InterceptorManager(), + }; /** - * @param config 自定义默认配置 + * @param defaults 自定义默认配置 */ - constructor(config: AxiosRequestConfig = {}) { - this.defaults = config; - this.interceptors = { - request: new InterceptorManager(), - response: new InterceptorManager(), - }; - } + constructor(public defaults: AxiosRequestConfig = {}) {} /** * 根据配置中的 url 和 params 生成一个 URI diff --git a/src/core/InterceptorManager.ts b/src/core/InterceptorManager.ts index df44568..84a58a2 100644 --- a/src/core/InterceptorManager.ts +++ b/src/core/InterceptorManager.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-15 17:50:50 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-23 09:16:23 + * @LastEditTime: 2020-04-23 20:54:24 */ import { InterceptorResolved, @@ -19,17 +19,12 @@ export default class InterceptorManagerStatic implements InterceptorManager>; - - constructor() { - this._id = 0; - this._interceptors = {}; - } + private _interceptors: Record> = {}; /** * 添加拦截器 diff --git a/src/core/createError.ts b/src/core/createError.ts index c232f63..57c92c4 100644 --- a/src/core/createError.ts +++ b/src/core/createError.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-14 22:23:39 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-23 10:34:18 + * @LastEditTime: 2020-04-23 23:47:26 */ import { AxiosRequestConfig, RequestConfig, AxiosResponse } from '../types'; @@ -13,22 +13,7 @@ class AxiosError extends Error { /** * 是 Axios 错误 */ - public isAxiosError: boolean; - - /** - * Axios 请求配置 - */ - public config: AxiosRequestConfig; - - /** - * 通用请求配置 - */ - public request: RequestConfig; - - /** - * Axios 响应体 - */ - public response?: AxiosResponse; + public isAxiosError = true; /** * @param message 错误信息 @@ -36,14 +21,14 @@ class AxiosError extends Error { * @param request 通用请求配置 * @param response Axios 响应体 */ - constructor(message: string, config: AxiosRequestConfig, request: RequestConfig, response?: AxiosResponse) { + constructor( + message: string, + public config: AxiosRequestConfig, + public request: RequestConfig, + public response?: AxiosResponse + ) { super(message); - this.isAxiosError = true; - this.config = config; - this.request = request; - this.response = response; - // 修复继承系统自带类 prototype 设置失败的问题 Object.setPrototypeOf(this, AxiosError.prototype); } diff --git a/src/core/mergeConfig.ts b/src/core/mergeConfig.ts index 04bb148..057de08 100644 --- a/src/core/mergeConfig.ts +++ b/src/core/mergeConfig.ts @@ -2,11 +2,31 @@ * @Author: early-autumn * @Date: 2020-04-15 22:48:25 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-21 10:43:39 + * @LastEditTime: 2020-04-23 23:55:19 */ import { AnyObject, AxiosRequestConfig } from '../types'; import { isPlainObject, deepMerge } from '../helpers/utils'; +type OnlyFromConfig2Key = 'url' | 'data'; +type PriorityFromConfig2Key = + | 'adapter' + | 'baseURL' + | 'method' + | 'validateStatus' + | 'paramsSerializer' + | 'transformRequest' + | 'transformResponse' + | 'errorHandler' + | 'cancelToken' + | 'dataType' + | 'responseType' + | 'timeout' + | 'enableHttp2' + | 'enableQuic' + | 'enableCache' + | 'sslVerify'; +type DeepMergeConfigKey = 'params' | 'headers'; + /** * 只取 config2 中的配置 * @@ -14,7 +34,7 @@ import { isPlainObject, deepMerge } from '../helpers/utils'; * @param config * @param config2 */ -function onlyFromConfig2(keys: ['url', 'data'], config: AxiosRequestConfig, config2: AxiosRequestConfig) { +function onlyFromConfig2(keys: OnlyFromConfig2Key[], config: AxiosRequestConfig, config2: AxiosRequestConfig) { keys.forEach((key) => { if (config2[key] !== undefined) { config[key] = config2[key] as any; @@ -31,24 +51,7 @@ function onlyFromConfig2(keys: ['url', 'data'], config: AxiosRequestConfig, conf * @param config2 */ function priorityFromConfig2( - keys: [ - 'adapter', - 'baseURL', - 'method', - 'validateStatus', - 'paramsSerializer', - 'transformRequest', - 'transformResponse', - 'errorHandler', - 'cancelToken', - 'dataType', - 'responseType', - 'timeout', - 'enableHttp2', - 'enableQuic', - 'enableCache', - 'sslVerify' - ], + keys: PriorityFromConfig2Key[], config: AxiosRequestConfig, config1: AxiosRequestConfig, config2: AxiosRequestConfig @@ -71,7 +74,7 @@ function priorityFromConfig2( * @param config2 */ function deepMergeConfig( - keys: ['headers', 'params'], + keys: DeepMergeConfigKey[], config: AxiosRequestConfig, config1: AxiosRequestConfig, config2: AxiosRequestConfig @@ -96,32 +99,30 @@ export default function mergeConfig( config2: AxiosRequestConfig = {} ): AxiosRequestConfig { const config: AxiosRequestConfig = {}; + const onlyFromConfig2Keys: OnlyFromConfig2Key[] = ['url', 'data']; + const priorityFromConfig2Keys: PriorityFromConfig2Key[] = [ + 'adapter', + 'baseURL', + 'method', + 'validateStatus', + 'paramsSerializer', + 'transformRequest', + 'transformResponse', + 'errorHandler', + 'cancelToken', + 'dataType', + 'responseType', + 'timeout', + 'enableHttp2', + 'enableQuic', + 'enableCache', + 'sslVerify', + ]; + const deepMergeConfigKeys: DeepMergeConfigKey[] = ['headers', 'params']; - onlyFromConfig2(['url', 'data'], config, config2); - priorityFromConfig2( - [ - 'adapter', - 'baseURL', - 'method', - 'validateStatus', - 'paramsSerializer', - 'transformRequest', - 'transformResponse', - 'errorHandler', - 'cancelToken', - 'dataType', - 'responseType', - 'timeout', - 'enableHttp2', - 'enableQuic', - 'enableCache', - 'sslVerify', - ], - config, - config1, - config2 - ); - deepMergeConfig(['headers', 'params'], config, config1, config2); + onlyFromConfig2(onlyFromConfig2Keys, config, config2); + priorityFromConfig2(priorityFromConfig2Keys, config, config1, config2); + deepMergeConfig(deepMergeConfigKeys, config, config1, config2); return config; } diff --git a/src/core/transformData.ts b/src/core/transformData.ts index ff7c143..926efe1 100644 --- a/src/core/transformData.ts +++ b/src/core/transformData.ts @@ -2,14 +2,14 @@ * @Author: early-autumn * @Date: 2020-04-16 22:37:44 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-17 13:42:13 + * @LastEditTime: 2020-04-23 23:09:24 */ import { Data, Headers, TransformData } from '../types'; /** * 转换数据 * - * @param data 请求数据或响应诗句 + * @param data 请求数据或响应数据 * @param headers 请求头或响应头 * @param transforms 请求数据转换函数或响应数据转换函数 */ diff --git a/src/core/transformRequest.ts b/src/core/transformRequest.ts index 401531a..d4fde41 100644 --- a/src/core/transformRequest.ts +++ b/src/core/transformRequest.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-17 15:05:43 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-20 13:41:15 + * @LastEditTime: 2020-04-24 08:53:57 */ import { AxiosRequestConfig, RequestConfig } from '../types'; import { pick } from '../helpers/utils'; @@ -11,17 +11,6 @@ import combineURL from '../helpers/combineURL'; import buildURL from '../helpers/buildURL'; import { methodToUppercase } from './transformMethod'; -type PickKeys = - | 'data' - | 'headers' - | 'dataType' - | 'responseType' - | 'timeout' - | 'enableHttp2' - | 'enableQuic' - | 'enableCache' - | 'sslVerify'; - /** * 根据配置中的 baseURL 和 url 和 params 生成完整 URL * @@ -42,25 +31,21 @@ function transformURL(config: AxiosRequestConfig): string { * @param config Axios 请求配置 */ export default function transformRequest(config: AxiosRequestConfig): RequestConfig { - const url = transformURL(config); - const method = methodToUppercase(config.method); - const pickRequest = pick( - config, - 'data', - 'headers', - 'dataType', - 'responseType', - 'timeout', - 'enableHttp2', - 'enableQuic', - 'enableCache', - 'sslVerify' - ); - return { - url, - method, + url: transformURL(config), + method: methodToUppercase(config.method), header: config.headers, - ...pickRequest, + ...pick( + config, + 'data', + 'headers', + 'dataType', + 'responseType', + 'timeout', + 'enableHttp2', + 'enableQuic', + 'enableCache', + 'sslVerify' + ), } as RequestConfig; } diff --git a/src/core/transformResponse.ts b/src/core/transformResponse.ts index db81d79..6b2df21 100644 --- a/src/core/transformResponse.ts +++ b/src/core/transformResponse.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-17 14:09:16 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-22 13:06:27 + * @LastEditTime: 2020-04-24 08:54:42 */ import { AxiosRequestConfig, AxiosResponse, Response } from '../types'; import { pick } from '../helpers/utils'; @@ -26,6 +26,6 @@ export default function transformResponse(response: Response, config: AxiosReque statusText, headers, config, - ...pick(response, 'data', 'cookies', 'profile'), + ...pick(response, 'data', 'cookies', 'profile'), }; } diff --git a/src/helpers/utils.ts b/src/helpers/utils.ts index 6d2c558..1f7e6b4 100644 --- a/src/helpers/utils.ts +++ b/src/helpers/utils.ts @@ -2,7 +2,7 @@ * @Author: early-autumn * @Date: 2020-04-13 21:55:40 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-22 13:02:06 + * @LastEditTime: 2020-04-23 22:38:30 */ import { AnyObject } from '../types'; diff --git a/src/types.ts b/src/types.ts index f476e51..37e8b64 100644 --- a/src/types.ts +++ b/src/types.ts @@ -2,13 +2,15 @@ * @Author: early-autumn * @Date: 2020-04-13 15:23:53 * @LastEditors: early-autumn - * @LastEditTime: 2020-04-23 10:43:58 + * @LastEditTime: 2020-04-24 09:00:02 */ /** * 任意值对象 */ -export declare type AnyObject = Record; +export declare interface AnyObject { + [x: string]: T; +} /** * 请求方法 @@ -38,52 +40,7 @@ export declare type Data = string | AnyObject | ArrayBuffer; /** * Axios 头 */ -export declare interface Headers { - /** - * 通用配置 - */ - common?: AnyObject; - - /** - * options 请求专用 - */ - options?: AnyObject; - - /** - * get 请求专用 - */ - get?: AnyObject; - - /** - * head 请求专用 - */ - head?: AnyObject; - - /** - * post 请求专用 - */ - post?: AnyObject; - - /** - * put 请求专用 - */ - put?: AnyObject; - - /** - * delete 请求专用 - */ - delete?: AnyObject; - - /** - * trace 请求专用 - */ - trace?: AnyObject; - - /** - * connect 请求专用 - */ - connect?: AnyObject; - +export declare interface Headers extends Partial>> { /** * 自定义配置 */ @@ -727,7 +684,7 @@ export declare interface AxiosInstance extends AxiosBaseInstance { * * @param config 自定义默认配置 */ - create(config?: AxiosRequestConfig): AxiosBaseInstance; + create(defaults?: AxiosRequestConfig): AxiosBaseInstance; /** * Axios 类