🚧 编写文档中...

pull/1/head
954270063@qq.com 2020-04-18 17:06:01 +08:00
parent 4890dbcfa2
commit 6f75dc5c12
20 changed files with 526 additions and 428 deletions

View File

@ -26,28 +26,29 @@ npm i axios-miniprogram
* 支持 `Promise` * 支持 `Promise`
* 支持 拦截器。 * 支持 拦截器。
* 支持 取消请求。 * 支持 取消请求。
* 支持 自定义合法状态码。
* 支持 自定义参数序列化。 * 支持 自定义参数序列化。
* 支持 自定义转换数据。 * 支持 自定义转换数据。
* 支持 自定义成功状态码。
* 支持 自定义平台适配器 * 支持 自定义平台适配器
## API ## 使用
可以通过将相关配置传递给`axios`来发送请求。 可以通过将相关配置传递给`axios`来发送请求。
### `axios(config)` ### `axios(config)`
```typescript ```typescript
// 默认发送 GET 请求 // 发送 GET 请求
axios({ axios({
method: 'get',
url: '/test', url: '/test',
params: { test: 1 } params: { test: 1 }
}); });
// 发送 POST 请求 // 发送 POST 请求
axios({ axios({
url: '/test',
method: 'post', method: 'post',
url: '/test',
data: { test: 1 } data: { test: 1 }
}); });
``` ```
@ -64,7 +65,7 @@ axios('/test/xxx');
axios('/test/xxx', { method: 'post' }); axios('/test/xxx', { method: 'post' });
``` ```
还可以使用请求方法别名来简化请求 还可以使用请求方法别名来简化请求
* ##### axios.request(config) * ##### axios.request(config)
* ##### axios.options(url, config?) * ##### axios.options(url, config?)
@ -106,6 +107,30 @@ axios.post('/test', { test: 1 }, {
}); });
``` ```
## 配置
|参数|类型|默认值|说明|平台差异
|:-|:-|:-|:-|:-|:-|:-|
|adapter|Function||
|baseURL|String||
|url|String||
|method|String|get|
|params|Object||
|data|String/Object/ArrayBuffer||
|headers|Object|[查看]()|
|validateStatus|Function||
|paramsSerializer|Function||
|transformRequest|Function/Array|
|transformResponse|Function/Array|
|cancelToken|Object|
|timeout|Number|0|
|dataType|String|json|
|responseType|String|text|
|enableHttp2|Boolean|false|
|enableQuic|Boolean|false|
|enableCache|Boolean|false|
|sslVerify|Boolean|false|
### 默认配置 ### 默认配置
##### 全局默认配置`axios.defaults` ##### 全局默认配置`axios.defaults`
@ -140,36 +165,27 @@ instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlenco
##### 配置优先顺序 ##### 配置优先顺序
发送请求时,会使用默认配置`defaults`和自定义配置`config`合并出请求配置`requestConfig`,然后用合并出的请求配置`requestConfig`去发送请求,多数情况下,后者优先于前者,具体合并策略可以参考 [mergeConfig.ts](https://github.com/early-autumn/axios-miniprogram/blob/master/src/helper/mergeConfig.ts) 的实现。 发送请求时,会使用默认配置`defaults`和自定义配置`config`合并出请求配置`requestConfig`,然后用合并出的请求配置`requestConfig`去发送请求,多数情况下,后者优先级要高于前者,具体合并策略可以参考 [mergeConfig.ts](https://github.com/early-autumn/axios-miniprogram/blob/master/src/helper/mergeConfig.ts) 的实现。
### `axios.getUri(config)` ### `axios.getUri(config)`
根据传入的配置生成完整的`URL`。 根据配置中的`url`和`params`生成一个`URI`。
```typescript ```typescript
axios.defaults.baseURL = 'https://www.xxx.com'; // uri === '/test?id=1'
// uri === 'https://www.xxx.com/test?id=1'
const uri = axios.getUri({ const uri = axios.getUri({
url: '/test', url: '/test',
params: { id: 1 } 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.create(config)`
创建一个`自定义实例`,传入的自定义配置`config`会和`axios`的默认配置`axios.defaults`合并成`自定义实例`的默认配置。 创建一个`自定义实例`,传入的自定义配置`config`会和`axios`的默认配置`axios.defaults`合并成`自定义实例`的默认配置。
`自定义实例`拥有和`axios`相同的调用方式和请求方法别名。 `自定义实例`拥有和`axios`相同的调用方式和请求方法的别名。
```typescript ```typescript
axios.defaults.baseURL = 'https://www.xxx.com'; axios.defaults.baseURL = 'https://www.xxx.com';

View File

@ -1,6 +0,0 @@
/*
* @Author: early-autumn
* @Date: 2020-04-05 01:56:05
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-05 01:56:06
*/

View File

@ -2,14 +2,9 @@
* @Author: early-autumn * @Author: early-autumn
* @Date: 2020-04-17 12:18:25 * @Date: 2020-04-17 12:18:25
* @LastEditors: early-autumn * @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 23:57:43 * @LastEditTime: 2020-04-18 16:04:27
*/ */
import { PlatformRequest } from '../types'; import { Adapter, Platform } from '../types';
interface Platform {
request?: PlatformRequest;
httpRequest?: PlatformRequest;
}
/* eslint-disable no-var */ /* eslint-disable no-var */
var wx: Platform; var wx: Platform;
@ -20,33 +15,33 @@ var qq: Platform;
var uni: Platform; var uni: Platform;
/** /**
* *
*/ */
let adapter: PlatformRequest | undefined; let request: Adapter | undefined;
/** /**
* *
*/ */
function adaptive(): void { function adaptive(): void {
switch (true) { switch (true) {
// 微信小程序 // 微信小程序
case wx !== undefined: case wx !== undefined:
adapter = wx.request; request = wx.request;
// 支付宝小程序 // 支付宝小程序
case my !== undefined: case my !== undefined:
adapter = my.request ?? my.httpRequest; request = my.request ?? my.httpRequest;
// 百度小程序 // 百度小程序
case swan !== undefined: case swan !== undefined:
adapter = swan.request; request = swan.request;
// 字节跳动小程序 // 字节跳动小程序
case tt !== undefined: case tt !== undefined:
adapter = tt.request; request = tt.request;
// QQ 小程序 // QQ 小程序
case qq !== undefined: case qq !== undefined:
adapter = qq.request; request = qq.request;
// uniapp // uniapp
case uni !== undefined: case uni !== undefined:
adapter = uni.request; request = uni.request;
default: default:
throw new Error('暂未适配此平台,您需要参阅文档使用自定义适配器手动适配当前平台'); throw new Error('暂未适配此平台,您需要参阅文档使用自定义适配器手动适配当前平台');
} }
@ -54,4 +49,4 @@ function adaptive(): void {
adaptive(); adaptive();
export default adapter; export default request;

View File

@ -0,0 +1,45 @@
/*
* @Author: early-autumn
* @Date: 2020-04-17 15:05:43
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-18 15:51:02
*/
import { Method, Data, Headers, AdapterMethod, AxiosRequestConfig, RequestConfig } from '../types';
import transformURL from '../helper/transformURL';
/**
*
*
* @param config Axios
*/
function methodUppercase(config: AxiosRequestConfig): AdapterMethod {
return (config.method as Method).toUpperCase() as AdapterMethod;
}
/**
* Axios
*
*
*
* @param config Axios
*/
export default function requestConfigOk(config: AxiosRequestConfig): RequestConfig {
const { headers, data, dataType, responseType, timeout, enableHttp2, enableQuic, enableCache, sslVerify } = config;
const url = transformURL(config);
const method = methodUppercase(config);
return {
url,
method,
header: headers as Headers,
headers: headers as Headers,
data: data as Data,
dataType,
responseType,
timeout,
enableHttp2,
enableQuic,
enableCache,
sslVerify,
};
}

41
src/adapter/response.ts Normal file
View File

@ -0,0 +1,41 @@
/*
* @Author: early-autumn
* @Date: 2020-04-17 14:09:16
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-18 16:03:37
*/
import { RequestConfig, AxiosRequestConfig, AxiosResponse, Response } from '../types';
/**
* Axios
*
*
*
* @param response
* @param request
* @param config Axios
*/
export default function responseOk(
response: Response,
request: RequestConfig,
config: AxiosRequestConfig
): AxiosResponse {
response.status = response.status ?? response.statusCode;
response.headers = response.headers ?? response.header;
const { status, headers, data, cookies, profile } = response;
const statusText = status === 200 ? 'OK' : status === 400 ? 'Bad Adapter' : '';
return {
status,
statusText,
headers,
data,
response,
request,
config,
cookies,
profile,
};
}

View File

@ -2,11 +2,10 @@
* @Author: early-autumn * @Author: early-autumn
* @Date: 2020-04-15 12:45:18 * @Date: 2020-04-15 12:45:18
* @LastEditors: early-autumn * @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 21:49:05 * @LastEditTime: 2020-04-18 15:32:21
*/ */
import { AxiosRequestConfig, Data, AxiosResponse, AxiosBaseInstance, AxiosInstance } from './types'; import { AxiosRequestConfig, Data, AxiosResponse, AxiosBaseInstance, AxiosInstance } from './types';
import Axios from './core/Axios'; import Axios from './core/Axios';
import Cancel from './cancel/Cancel';
import CancelToken from './cancel/CancelToken'; import CancelToken from './cancel/CancelToken';
import isCancel from './cancel/isCancel'; import isCancel from './cancel/isCancel';
import mergeConfig from './helper/mergeConfig'; import mergeConfig from './helper/mergeConfig';
@ -63,16 +62,17 @@ function createInstance(config: AxiosRequestConfig): AxiosInstance {
const axios = createInstance(defaults); const axios = createInstance(defaults);
// 添加 create 工厂方法 // 添加 create 工厂方法
axios.create = function create(config: AxiosRequestConfig): AxiosBaseInstance { axios.create = function create(config: AxiosRequestConfig = {}): AxiosBaseInstance {
return createInstance(mergeConfig(axios.defaults, config)); return createInstance(mergeConfig(axios.defaults, config));
}; };
// 添加 Axios 类 // 添加 Axios 类
axios.Axios = Axios; axios.Axios = Axios;
// 添加取消相关 // 添加 CancelToken 类
axios.Cancel = Cancel;
axios.CancelToken = CancelToken; axios.CancelToken = CancelToken;
// 添加判断取消方法
axios.isCancel = isCancel; axios.isCancel = isCancel;
export default axios; export default axios;

View File

@ -2,19 +2,14 @@
* @Author: early-autumn * @Author: early-autumn
* @Date: 2020-04-13 18:00:27 * @Date: 2020-04-13 18:00:27
* @LastEditors: early-autumn * @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 19:14:14 * @LastEditTime: 2020-04-18 16:17:08
*/ */
import { AxiosMethod, Params, Data, Interceptors, AxiosRequestConfig, AxiosResponse, Axios } from '../types'; import { Method, Params, Data, Interceptors, AxiosRequestConfig, AxiosResponse, Axios } from '../types';
import transformURL from '../helper/transformURL'; import buildURL from '../helper/buildURL';
import mergeConfig from '../helper/mergeConfig'; import mergeConfig from '../helper/mergeConfig';
import InterceptorManager from './InterceptorManager'; import InterceptorManager from './InterceptorManager';
import dispatchRequest from './dispatchRequest'; import dispatchRequest from './dispatchRequest';
interface PromiseCatch {
request: Promise<AxiosRequestConfig>;
response?: Promise<AxiosResponse>;
}
export default class AxiosStatic implements Axios { export default class AxiosStatic implements Axios {
/** /**
* *
@ -26,7 +21,7 @@ export default class AxiosStatic implements Axios {
*/ */
public interceptors: Interceptors; public interceptors: Interceptors;
constructor(config: AxiosRequestConfig) { constructor(config: AxiosRequestConfig = {}) {
this.defaults = config; this.defaults = config;
this.interceptors = { this.interceptors = {
request: new InterceptorManager<AxiosRequestConfig>(), request: new InterceptorManager<AxiosRequestConfig>(),
@ -35,40 +30,42 @@ export default class AxiosStatic implements Axios {
} }
/** /**
* baseURL + url + params * url params URI
* *
* @param config * @param config Axios
*/ */
public getUri(config: AxiosRequestConfig): string { public getUri(config: AxiosRequestConfig): string {
return transformURL(mergeConfig(this.defaults, config)); config = mergeConfig(this.defaults, config);
return buildURL((config.url = ''), config.params, config.paramsSerializer).replace(/^\?/, '');
} }
/** /**
* HTTP * HTTP
* *
* @param config * @param config Axios
*/ */
public request<T extends Data>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> { public request<T extends Data>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
config = mergeConfig(this.defaults, config); config = mergeConfig(this.defaults, config);
const promise: PromiseCatch = { let promiseRequest = Promise.resolve(config);
request: Promise.resolve(config),
};
// 执行前置拦截器 // 执行前置拦截器
this.interceptors.request.forEach(function executor({ resolved, rejected }) { this.interceptors.request.forEach(function executor({ resolved, rejected }) {
promise.request = promise.request.then(resolved, rejected); promiseRequest = promiseRequest.then(resolved, rejected);
}, 'reverse'); }, 'reverse');
// 发送请求 // 发送请求
promise.response = promise.request.then(dispatchRequest, (err: any) => Promise.reject(err)); let promisePesponse = promiseRequest.then(dispatchRequest, (err: any) => Promise.reject(err)) as Promise<
AxiosResponse<T>
>;
// 执行后置拦截器 // 执行后置拦截器
this.interceptors.response.forEach(function executor({ resolved, rejected }) { this.interceptors.response.forEach(function executor({ resolved, rejected }) {
promise.response = promise.response?.then(resolved, rejected); promisePesponse = promisePesponse.then(resolved, rejected);
}); });
return promise.response as Promise<AxiosResponse<T>>; return promisePesponse;
} }
/** /**
@ -168,7 +165,7 @@ export default class AxiosStatic implements Axios {
* @param config * @param config
*/ */
private _requestMethodWithoutParams<T extends Data>( private _requestMethodWithoutParams<T extends Data>(
method: AxiosMethod, method: Method,
url: string, url: string,
params?: Params, params?: Params,
config: AxiosRequestConfig = {} config: AxiosRequestConfig = {}
@ -190,7 +187,7 @@ export default class AxiosStatic implements Axios {
* @param config * @param config
*/ */
private _requestMethodWithoutData<T extends Data>( private _requestMethodWithoutData<T extends Data>(
method: AxiosMethod, method: Method,
url: string, url: string,
data?: Data, data?: Data,
config: AxiosRequestConfig = {} config: AxiosRequestConfig = {}

View File

@ -2,9 +2,9 @@
* @Author: early-autumn * @Author: early-autumn
* @Date: 2020-04-14 22:23:39 * @Date: 2020-04-14 22:23:39
* @LastEditors: early-autumn * @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 15:57:29 * @LastEditTime: 2020-04-18 14:20:08
*/ */
import { AxiosRequestConfig, PlatformRequestConfig, AxiosResponse } from '../types'; import { AxiosRequestConfig, RequestConfig, AxiosResponse } from '../types';
/** /**
* AxiosError Error * AxiosError Error
@ -21,16 +21,16 @@ class AxiosError extends Error {
config: AxiosRequestConfig; config: AxiosRequestConfig;
/** /**
* *
*/ */
request: PlatformRequestConfig; request: RequestConfig;
/** /**
* *
*/ */
response?: AxiosResponse; response?: AxiosResponse;
constructor(message: string, config: AxiosRequestConfig, request: PlatformRequestConfig, response?: AxiosResponse) { constructor(message: string, config: AxiosRequestConfig, request: RequestConfig, response?: AxiosResponse) {
super(message); super(message);
this.isAxiosError = true; this.isAxiosError = true;
@ -50,13 +50,13 @@ class AxiosError extends Error {
* *
* @param message * @param message
* @param config Axios * @param config Axios
* @param request * @param request
* @param response * @param response Axios
*/ */
export default function createError( export default function createError(
message: string, message: string,
config: AxiosRequestConfig, config: AxiosRequestConfig,
request: PlatformRequestConfig, request: RequestConfig,
response?: AxiosResponse response?: AxiosResponse
): AxiosError { ): AxiosError {
return new AxiosError(message, config, request, response); return new AxiosError(message, config, request, response);

View File

@ -2,16 +2,18 @@
* @Author: early-autumn * @Author: early-autumn
* @Date: 2020-04-13 18:01:16 * @Date: 2020-04-13 18:01:16
* @LastEditors: early-autumn * @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 23:52:47 * @LastEditTime: 2020-04-18 15:53:05
*/ */
import { AnyObject, Method, AxiosRequestConfig, AxiosResponse, Data } from '../types'; import { AxiosRequestConfig, AxiosResponse } from '../types';
import { merge } from '../helper/utils'; import flattenHeaders from '../helper/flattenHeaders';
import transformData from '../helper/transformData'; import transformData from '../helper/transformData';
import isCancel from '../cancel/isCancel'; import isCancel from '../cancel/isCancel';
import requestAdapter from './requestAdapter'; import request from './request';
/** /**
* , * ,
*
* @param config Axios
*/ */
function throwIfCancellationRequested(config: AxiosRequestConfig) { function throwIfCancellationRequested(config: AxiosRequestConfig) {
if (config.cancelToken) { if (config.cancelToken) {
@ -22,31 +24,23 @@ function throwIfCancellationRequested(config: AxiosRequestConfig) {
/** /**
* *
* *
* @param config * @param config Axios
*/ */
export default function dispatchRequest(config: AxiosRequestConfig): Promise<AxiosResponse> { export default function dispatchRequest(config: AxiosRequestConfig): Promise<AxiosResponse> {
throwIfCancellationRequested(config); throwIfCancellationRequested(config);
const { method = 'GET', data = {}, headers = {} } = config; if (config.method === undefined) {
config.method = 'get';
}
// 把方法转成全大写 config.headers = flattenHeaders(config);
config.method = method.toUpperCase() as Method;
// 合并 headers config.data = transformData(config.data ?? {}, config.headers, config.transformRequest);
config.headers = merge(
headers.common ?? {},
(headers[(config.method as string).toLowerCase()] ?? {}) as AnyObject,
headers
);
// 转换请求数据
config.data = transformData(data, config.headers, config.transformResponse);
function onResolved(response: AxiosResponse): AxiosResponse { function onResolved(response: AxiosResponse): AxiosResponse {
throwIfCancellationRequested(config); throwIfCancellationRequested(config);
// 转换响应数据 response.data = transformData(response.data, response.headers, config.transformResponse);
response.data = transformData(response.data, response.headers, config.transformResponse) as Data;
return response; return response;
} }
@ -55,18 +49,13 @@ export default function dispatchRequest(config: AxiosRequestConfig): Promise<Axi
if (!isCancel(reason)) { if (!isCancel(reason)) {
throwIfCancellationRequested(config); throwIfCancellationRequested(config);
// Transform response data if (reason.response !== undefined) {
if (reason && reason.response !== undefined) { reason.response.data = transformData(reason.response.data, reason.response.headers, config.transformResponse);
reason.response.data = transformData(
reason.response.data,
reason.response.headers,
config.transformResponse
) as Data;
} }
} }
return Promise.reject(reason); return Promise.reject(reason);
} }
return requestAdapter(config).then(onResolved, onRejected); return request(config).then(onResolved, onRejected);
} }

74
src/core/request.ts Normal file
View File

@ -0,0 +1,74 @@
/*
* @Author: early-autumn
* @Date: 2020-04-16 00:48:45
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-18 15:56:12
*/
import { AxiosRequestConfig, AxiosResponse, Response } from '../types';
import createError from '../core/createError';
import requestAdapter from '../adapter/request';
import requestConfigAdapter from '../adapter/requestConfig';
import responseAdapter from '../adapter/response';
/**
*
*
* @param config Axios
*/
export default function request(config: AxiosRequestConfig): Promise<AxiosResponse> {
return new Promise(function dispatchAdapter(resolve, reject): void {
const { adapter = requestAdapter, cancelToken } = config;
const request = requestConfigAdapter(config);
/**
*
*
* @param message
* @param response Axios
*/
function catchError(message: any, response?: AxiosResponse): void {
if (typeof message !== 'string') {
message = '配置不正确或者网络异常';
}
reject(createError(message, config, request, response));
}
if (adapter === undefined) {
catchError('平台适配失败,您需要参阅文档使用自定义适配器手动适配当前平台');
return;
}
/**
*
*
* @param res
*/
function validateStatus(res: Response): void {
const response = responseAdapter(res, request, config);
if (config.validateStatus === undefined || config.validateStatus(response.status)) {
resolve(response);
} else {
catchError(`请求失败,状态码为 ${status}`, response);
}
}
// 使用适配器发送请求
const task = adapter({
...request,
success: validateStatus,
fail: catchError,
});
// 如果存在取消令牌
// 则调用取消令牌里的 listener 监听用户的取消操作
if (cancelToken !== undefined) {
cancelToken.listener.then(function onCanceled(reason): void {
task.abort();
reject(reason);
});
}
});
}

View File

@ -1,75 +0,0 @@
/*
* @Author: early-autumn
* @Date: 2020-04-16 00:48:45
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 22:18:07
*/
import { AxiosRequestConfig, AxiosResponse, PlatformResponse } from '../types';
import transformRequest from '../helper/transformRequest';
import transformResponse from '../helper/transformResponse';
import autoAdapter from '../adapter/autoAdapter';
import createError from './createError';
/**
*
*
* @param config
*/
export default function requestAdapter(config: AxiosRequestConfig): Promise<AxiosResponse> {
return new Promise(function dispatchRequestAdapter(resolve, reject): void {
const { adapter = autoAdapter, cancelToken } = config;
const requestConfig = transformRequest(config);
/**
*
*
* @param param0
* @param response
*/
function catchError(message: any, response?: AxiosResponse): void {
if (typeof message !== 'string') {
message = '网络错误';
}
reject(createError(message, config, requestConfig, response));
}
if (adapter === undefined) {
catchError('平台适配失败,您需要参阅文档使用自定义适配器手动适配当前平台');
return;
}
/**
*
*
* @param result
*/
function checkStatusCode(result: PlatformResponse): void {
const response = transformResponse(result, config);
if (config.validateStatus === undefined || config.validateStatus(response.status)) {
resolve(response);
} else {
catchError(`请求失败,状态码为 ${status}`, response);
}
}
// 发送请求
const requestTask = adapter({
...requestConfig,
success: checkStatusCode,
fail: catchError,
});
// 如果存在取消令牌
// 则调用取消令牌里的 listener 监听用户的取消操作
if (cancelToken !== undefined) {
cancelToken.listener.then(function onCanceled(reason): void {
requestTask.abort();
reject(reason);
});
}
});
}

View File

@ -2,7 +2,7 @@
* @Author: early-autumn * @Author: early-autumn
* @Date: 2020-04-13 21:45:45 * @Date: 2020-04-13 21:45:45
* @LastEditors: early-autumn * @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 23:54:41 * @LastEditTime: 2020-04-18 16:12:10
*/ */
import { AnyObject, Params } from '../types'; import { AnyObject, Params } from '../types';
import { isPlainObject, isDate } from './utils'; import { isPlainObject, isDate } from './utils';
@ -89,7 +89,7 @@ function paramsSerializerDefault(params: AnyObject): string {
* @param params * @param params
* @param paramsSerializer * @param paramsSerializer
*/ */
export default function processURL( export default function buildURL(
url: string, url: string,
params?: Params, params?: Params,
paramsSerializer?: (params: AnyObject) => string paramsSerializer?: (params: AnyObject) => string

View File

@ -2,7 +2,7 @@
* @Author: early-autumn * @Author: early-autumn
* @Date: 2020-04-15 22:09:38 * @Date: 2020-04-15 22:09:38
* @LastEditors: early-autumn * @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 23:45:11 * @LastEditTime: 2020-04-18 17:00:38
*/ */
import { AxiosRequestConfig } from '../types'; import { AxiosRequestConfig } from '../types';
@ -29,6 +29,12 @@ const defaults: AxiosRequestConfig = {
return status >= 200 && status < 300; return status >= 200 && status < 300;
}, },
timeout: 0, timeout: 0,
dataType: 'json',
responseType: 'text',
enableHttp2: false,
enableQuic: false,
enableCache: false,
sslVerify: false,
}; };
export default defaults; export default defaults;

View File

@ -0,0 +1,26 @@
/*
* @Author: early-autumn
* @Date: 2020-04-18 12:00:01
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-18 15:40:23
*/
import { AliasMethod, Headers, AxiosRequestConfig } from '../types';
import { merge } from './utils';
/**
*
*
* @param config Axios
*/
export default function flattenHeaders(config: AxiosRequestConfig): Headers {
let { headers = {} } = config;
const method = (config.method as string).toLowerCase() as AliasMethod;
headers = merge(headers.common ?? {}, headers[method] ?? {}, headers);
['delete', 'get', 'head', 'post', 'put', 'patch', 'common'].forEach((key: string) => {
delete headers[key];
});
return headers;
}

View File

@ -2,7 +2,7 @@
* @Author: early-autumn * @Author: early-autumn
* @Date: 2020-04-15 22:48:25 * @Date: 2020-04-15 22:48:25
* @LastEditors: early-autumn * @LastEditors: early-autumn
* @LastEditTime: 2020-04-18 00:03:08 * @LastEditTime: 2020-04-18 14:56:44
*/ */
import { AxiosRequestConfig } from '../types'; import { AxiosRequestConfig } from '../types';
import { isPlainObject, deepMerge } from './utils'; import { isPlainObject, deepMerge } from './utils';
@ -49,10 +49,10 @@ function priorityFromConfig2(
keys: [ keys: [
'baseURL', 'baseURL',
'method', 'method',
'validateStatus',
'paramsSerializer',
'transformRequest', 'transformRequest',
'transformResponse', 'transformResponse',
'paramsSerializer',
'validateStatus',
'cancelToken', 'cancelToken',
'dataType', 'dataType',
'responseType', 'responseType',
@ -103,24 +103,25 @@ function deepMergeConfig(
} }
/** /**
* * Axios
* *
* @param config1 1 * @param config1 Axios 1
* @param config2 2 * @param config2 Axios 2
*/ */
export default function mergeConfig(config1: AxiosRequestConfig, config2: AxiosRequestConfig): AxiosRequestConfig { export default function mergeConfig(config1: AxiosRequestConfig, config2: AxiosRequestConfig): AxiosRequestConfig {
const config: AxiosRequestConfig = {}; const config: AxiosRequestConfig = {};
onlyFromConfig1(['adapter'], config, config1); onlyFromConfig1(['adapter'], config, config1);
onlyFromConfig2(['url', 'data'], config, config2); onlyFromConfig2(['url', 'data'], config, config2);
deepMergeConfig(['headers', 'params'], config, config1, config2);
priorityFromConfig2( priorityFromConfig2(
[ [
'baseURL', 'baseURL',
'method', 'method',
'validateStatus',
'paramsSerializer',
'transformRequest', 'transformRequest',
'transformResponse', 'transformResponse',
'paramsSerializer',
'validateStatus',
'cancelToken', 'cancelToken',
'dataType', 'dataType',
'responseType', 'responseType',
@ -134,7 +135,6 @@ export default function mergeConfig(config1: AxiosRequestConfig, config2: AxiosR
config1, config1,
config2 config2
); );
deepMergeConfig(['headers', 'params'], config, config1, config2);
return config; return config;
} }

View File

@ -1,17 +0,0 @@
/*
* @Author: early-autumn
* @Date: 2020-04-17 15:05:43
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 22:22:50
*/
import { Method, AxiosRequestConfig, PlatformRequestConfig } from '../types';
import transformURL from './transformURL';
export default function transformRequest(config: AxiosRequestConfig): PlatformRequestConfig {
return {
...config,
url: transformURL(config),
method: config.method as Method,
header: config.headers,
};
}

View File

@ -1,28 +0,0 @@
/*
* @Author: early-autumn
* @Date: 2020-04-17 14:09:16
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 15:36:52
*/
import { AxiosRequestConfig, AxiosResponse, PlatformResponse } from '../types';
/**
* ,
*
* @param response
* @param config
*/
export default function transformResponse(response: PlatformResponse, config: AxiosRequestConfig): AxiosResponse {
const { status, statusCode, headers, header, ...attrPoint } = response;
const responseStatus = status ?? statusCode;
const responseHeaders = headers ?? header;
const responseStatusText = responseStatus === 200 ? 'OK' : responseStatus === 400 ? 'Bad PlatformRequest' : '';
return {
...attrPoint,
status: responseStatus,
statusText: responseStatusText,
headers: responseHeaders,
config,
};
}

View File

@ -2,14 +2,14 @@
* @Author: early-autumn * @Author: early-autumn
* @Date: 2020-04-17 00:00:21 * @Date: 2020-04-17 00:00:21
* @LastEditors: early-autumn * @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 00:09:47 * @LastEditTime: 2020-04-18 16:21:17
*/ */
import { AxiosRequestConfig } from '../types'; import { AxiosRequestConfig } from '../types';
import { isAbsoluteURL, combineURL } from './utils'; import { isAbsoluteURL, combineURL } from './utils';
import processURL from './processURL'; import buildURL from './buildURL';
/** /**
* baseURL + url + params * baseURL url params URL
* *
* @param config * @param config
*/ */
@ -17,5 +17,5 @@ export default function transformURL(config: AxiosRequestConfig): string {
const { baseURL = '', url = '', params, paramsSerializer } = config; const { baseURL = '', url = '', params, paramsSerializer } = config;
const fullURL = isAbsoluteURL(url) ? url : combineURL(baseURL, url); const fullURL = isAbsoluteURL(url) ? url : combineURL(baseURL, url);
return processURL(fullURL, params, paramsSerializer); return buildURL(fullURL, params, paramsSerializer);
} }

View File

@ -2,27 +2,13 @@
* @Author: early-autumn * @Author: early-autumn
* @Date: 2020-04-14 23:22:52 * @Date: 2020-04-14 23:22:52
* @LastEditors: early-autumn * @LastEditors: early-autumn
* @LastEditTime: 2020-04-17 15:41:23 * @LastEditTime: 2020-04-18 15:17:50
*/ */
import axios from './axios'; import axios from './axios';
/** /**
* typescript * typescript
*/ */
export { export * from './types';
AxiosMethod,
AxiosRequestConfig,
AxiosResponse,
Axios,
AxiosBaseInstance,
AxiosInstance,
AxiosError,
CancelAction,
CancelTokenSource,
CancelToken,
} from './types';
/**
* Axios
*/
export default axios; export default axios;

View File

@ -2,46 +2,40 @@
* @Author: early-autumn * @Author: early-autumn
* @Date: 2020-04-13 15:23:53 * @Date: 2020-04-13 15:23:53
* @LastEditors: early-autumn * @LastEditors: early-autumn
* @LastEditTime: 2020-04-18 00:02:38 * @LastEditTime: 2020-04-18 17:00:57
*/ */
// import 'miniprogram-api-typings';
export interface PlatformRequestTask {
/**
*
*/
abort(): void;
}
/**
*
*/
export interface PlatformRequest {
(config: PlatformRequestConfig): PlatformRequestTask;
}
/** /**
* *
*/ */
export declare type AnyObject = Record<string, any>; export declare type AnyObject = Record<string, any>;
/** /**
* Axios *
*/ */
export declare type Method = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT'; export declare type AdapterMethod = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT';
/** /**
* Axios *
*/
export declare type AliasMethod = 'options' | 'get' | 'head' | 'post' | 'put' | 'delete' | 'trace' | 'connect';
/**
* Axios
*/
export declare type Method = AliasMethod | AdapterMethod;
/**
* Axios
*/ */
export declare type Params = AnyObject; export declare type Params = AnyObject;
/** /**
* Axios * Axios
*/ */
export declare type Data = string | AnyObject | ArrayBuffer; export declare type Data = string | AnyObject | ArrayBuffer;
/** /**
* Axios * Axios
*/ */
export interface Headers { export interface Headers {
/** /**
@ -92,41 +86,171 @@ export interface Headers {
/** /**
* *
*/ */
[x: string]: string | Record<string, string> | undefined; [x: string]: Record<string, string> | string | undefined;
} }
/** /**
* *
*/
export interface RequestConfig {
/**
*
*/
url: string;
/**
* HTTP
*/
method: AdapterMethod;
/**
*
*/
data: Data;
/**
* Header headers
*/
header: AnyObject;
/**
* Headers header
*/
headers: AnyObject;
/**
*
*/
dataType?: 'json' | '其他';
/**
*
*/
responseType?: 'text' | 'arraybuffer';
/**
*
*/
timeout?: number;
/**
* http2
*/
enableHttp2?: boolean;
/**
* quic
*/
enableQuic?: boolean;
/**
* cache
*/
enableCache?: boolean;
/**
* ssl
*/
sslVerify?: boolean;
}
/**
*
*/
export interface Response {
/**
*
*/
statusCode: number;
/**
* Headers
*/
header: AnyObject;
/**
*
*/
status: number;
/**
* Headers
*/
headers: Headers;
/**
*
*/
data: Data;
/**
* cookies
*/
cookies?: string[];
/**
*
*/
profile?: AnyObject;
}
/**
*
*/
export interface AdapterRequestConfig extends RequestConfig {
/**
*
*/
success: (res: Response) => void;
/**
*
*/
fail: (err: unknown) => void;
}
/**
*
*/
export interface AdapterRequestTask {
/**
*
*/
abort(): void;
}
/**
*
*/
export interface Adapter {
(config: AdapterRequestConfig): AdapterRequestTask;
}
/**
*
*/
export interface Platform {
// 请求函数
request?: Adapter;
// 兼容支付宝小程序
httpRequest?: Adapter;
}
/**
*
*/ */
export interface TransformData { export interface TransformData {
(data: Data, headers: Headers): Data; (data: Data, headers: Headers): Data;
} }
/** /**
* Axios * Axios
*/
export declare type AxiosMethod = 'options' | 'get' | 'head' | 'post' | 'put' | 'delete' | 'trace' | 'connect' | Method;
/**
*
*/ */
export declare interface AxiosRequestConfig { export declare interface AxiosRequestConfig {
/** /**
* *
*
* uniapp :
*
* ```typescript
* import axios from 'axios-miniprogram';
*
* // 使用全局默认配置进行适配
* axios.defaults.adapter = uni.request;
*
* // 现在可以正常发送请求了
* axios('/test')
* ```
*/ */
adapter?: PlatformRequest; adapter?: Adapter;
/** /**
* *
@ -134,14 +258,14 @@ export declare interface AxiosRequestConfig {
baseURL?: string; baseURL?: string;
/** /**
* *
*/ */
url?: string; url?: string;
/** /**
* HTTP *
*/ */
method?: AxiosMethod; method?: Method;
/** /**
* *
@ -158,6 +282,16 @@ export declare interface AxiosRequestConfig {
*/ */
headers?: Headers; headers?: Headers;
/**
*
*/
validateStatus?: (status: number) => boolean;
/**
*
*/
paramsSerializer?: (params: AnyObject) => string;
/** /**
* *
*/ */
@ -168,123 +302,83 @@ export declare interface AxiosRequestConfig {
*/ */
transformResponse?: TransformData | TransformData[]; transformResponse?: TransformData | TransformData[];
/**
*
*/
paramsSerializer?: (params: AnyObject) => string;
/**
*
*/
validateStatus?: (status: number) => boolean;
/** /**
* *
*/ */
cancelToken?: CancelToken; cancelToken?: CancelToken;
/**
*
*/
dataType?: 'json' | '其他';
/**
*
*/
responseType?: 'text' | 'arraybuffer';
/** /**
* *
*/ */
timeout?: number; timeout?: number;
//===以下属性均在指定平台有效===// /**
*
*/
dataType?: 'json' | '其他';
/**
*
*/
responseType?: 'text' | 'arraybuffer';
/** /**
* wx
*
* http2 * http2
*/ */
enableHttp2?: boolean; enableHttp2?: boolean;
/** /**
* wx
*
* quic * quic
*/ */
enableQuic?: boolean; enableQuic?: boolean;
/** /**
* wx
*
* cache * cache
*/ */
enableCache?: boolean; enableCache?: boolean;
/** /**
* uniapp
*
* ssl * ssl
*/ */
sslVerify?: boolean; sslVerify?: boolean;
} }
/** /**
* * Axios
*/
export interface PlatformRequestConfig extends AxiosRequestConfig {
/**
*
*/
url: string;
/**
* method
*/
method: Method;
/**
* headers
*/
header?: AnyObject;
/**
*
*/
success?: (res: PlatformResponse) => void;
/**
*
*/
fail?: (err: any) => void;
}
/**
*
*/ */
export interface AxiosResponse<T extends Data = Data> { export interface AxiosResponse<T extends Data = Data> {
/** /**
* *
*/ */
status: number; status: number;
/** /**
* *
*/ */
statusText: string; statusText: string;
/** /**
* *
*/ */
data: T; data: T;
/** /**
* Headers *
*/ */
headers: Headers; headers: Headers;
/** /**
* *
*/
response: Response;
/**
*
*/
request: RequestConfig;
/**
* Axios
*/ */
config: AxiosRequestConfig; config: AxiosRequestConfig;
@ -299,46 +393,6 @@ export interface AxiosResponse<T extends Data = Data> {
profile?: AnyObject; profile?: AnyObject;
} }
/**
*
*/
export interface PlatformResponse {
/**
*
*/
statusCode: number;
/**
* Headers
*/
header: AnyObject;
/**
*
*/
status?: number;
/**
* Headers
*/
headers?: Headers;
/**
*
*/
data: Data;
/**
* cookies
*/
cookies?: string[];
/**
*
*/
profile?: AnyObject;
}
/** /**
* *
*/ */
@ -418,7 +472,7 @@ export interface Interceptors {
} }
/** /**
* Axios * Axios
*/ */
export interface Axios { export interface Axios {
/** /**
@ -432,7 +486,7 @@ export interface Axios {
interceptors: Interceptors; interceptors: Interceptors;
/** /**
* baseURL + url + params * url params URI
* *
* @param config * @param config
*/ */
@ -540,9 +594,9 @@ export interface AxiosError extends Error {
config: AxiosRequestConfig; config: AxiosRequestConfig;
/** /**
* *
*/ */
request: PlatformRequestConfig; request: RequestConfig;
/** /**
* *
@ -671,30 +725,25 @@ export interface AxiosBaseInstance extends Axios {
* * * *
*/ */
export interface AxiosInstance extends AxiosBaseInstance { export interface AxiosInstance extends AxiosBaseInstance {
/**
* Axios
*
* @param config
*/
create(config?: AxiosRequestConfig): AxiosBaseInstance;
/** /**
* Axios * Axios
*/ */
Axios: AxiosConstructor; Axios: AxiosConstructor;
/** /**
* Axios *
*
* @param config
*/
create(config: AxiosRequestConfig): AxiosBaseInstance;
/**
* Cancel
*/
Cancel: CancelConstructor;
/**
* CancelToken
*/ */
CancelToken: CancelTokenConstructor; CancelToken: CancelTokenConstructor;
/** /**
* *
* *
* @param value * @param value
*/ */