pull/8/head
zjx0905 2020-10-20 11:31:37 +08:00
parent 58f0b7ac49
commit 59b89e2ae1
35 changed files with 302 additions and 3574 deletions

5
.gitignore vendored
View File

@ -108,3 +108,8 @@ dist
coverage coverage
yarn-error.log yarn-error.log
es
lib
types

430
README.md
View File

@ -22,16 +22,16 @@ $ npm i axios-miniprogram
小程序平台专用请求库,实现了 [axios](https://github.com/axios/axios) 大部分功能,用法只存在少许差异,如果您是 [axios](https://github.com/axios/axios) 的老用户,那么不需要学习就可以直接上手使用。 小程序平台专用请求库,实现了 [axios](https://github.com/axios/axios) 大部分功能,用法只存在少许差异,如果您是 [axios](https://github.com/axios/axios) 的老用户,那么不需要学习就可以直接上手使用。
* 支持 微信小程序、支付宝小程序、百度小程序、字节跳动小程序、QQ 小程序、uniapp。 - 支持 微信小程序、支付宝小程序、百度小程序、字节跳动小程序、QQ 小程序、uniapp。
* 支持 `Typescript`,健全的类型系统,智能的 `IDE` 提示。 - 支持 `Typescript`,健全的类型系统,智能的 `IDE` 提示。
* 支持 `Promise` - 支持 `Promise`
* 支持 拦截器。 - 支持 拦截器。
* 支持 取消请求。 - 支持 取消请求。
* 支持 自定义合法状态码。 - 支持 自定义合法状态码。
* 支持 自定义参数序列化。 - 支持 自定义参数序列化。
* 支持 自定义转换数据。 - 支持 自定义转换数据。
* 支持 自定义错误处理。 - 支持 自定义错误处理。
* 支持 自定义平台适配器 - 支持 自定义平台适配器
## 使用 ## 使用
@ -42,25 +42,33 @@ $ npm i axios-miniprogram
```typescript ```typescript
// 发送 GET 请求 // 发送 GET 请求
axios({ axios({
method: 'get', url: "/user",
url: '/test', method: "get",
params: { test: 1 } params: {
}).then((response) => { id: 1,
// 请求成功后做些什么 },
}).catch((error) => { })
// 请求失败后做些什么 .then((response) => {
}); // 请求成功后做些什么
})
.catch((error) => {
// 请求失败后做些什么
});
// 发送 POST 请求 // 发送 POST 请求
axios({ axios({
method: 'post', url: "/user",
url: '/test', method: "post",
data: { test: 1 } data: {
}).then((response) => { id: 1,
// 请求成功后做些什么 },
}).catch((error) => { })
// 请求失败后做些什么 .then((response) => {
}); // 请求成功后做些什么
})
.catch((error) => {
// 请求失败后做些什么
});
``` ```
### `axios(url, config?)` ### `axios(url, config?)`
@ -69,129 +77,150 @@ axios({
```typescript ```typescript
// 默认发送 GET 请求 // 默认发送 GET 请求
axios('/test/xxx').then((response) => { axios("/user")
// 请求成功后做些什么 .then((response) => {
}).catch((error) => { // 请求成功后做些什么
// 请求失败后做些什么 })
}); .catch((error) => {
// 请求失败后做些什么
});
// 发送 POST 请求 // 发送 POST 请求
axios('/test/xxx', { method: 'post' }).then((response) => { axios("/user", {
// 请求成功后做些什么 method: "post",
}).catch((error) => { })
// 请求失败后做些什么 .then((response) => {
}); // 请求成功后做些什么
})
.catch((error) => {
// 请求失败后做些什么
});
``` ```
还可以使用请求方法的别名来简化请求。 还可以使用请求方法的别名来简化请求。
* ##### axios.request(config) - ##### axios.request(config)
* ##### axios.options(url, config?) - ##### axios.options(url, config?)
* ##### axios.get(url, params?, config?) - ##### axios.get(url, params?, config?)
* ##### axios.head(url, params?, config?) - ##### axios.head(url, params?, config?)
* ##### axios.post(url, data?, config?) - ##### axios.post(url, data?, config?)
* ##### axios.put(url, data?, config?) - ##### axios.put(url, data?, config?)
* ##### axios.delete(url, params?, config?) - ##### axios.delete(url, params?, config?)
* ##### axios.trace(url, config?) - ##### axios.trace(url, config?)
* ##### axios.connect(url, config?) - ##### axios.connect(url, config?)
常用例子,其他同理: 常用例子,其他同理:
```typescript ```typescript
// 发送 GET 请求 // 发送 GET 请求
axios.get('/test'); axios.get("/user");
// 携带参数 // 携带参数
axios.get('/test', { test: 1 }); axios.get("/user", {
test: 1,
});
// 携带额外配置 // 携带额外配置
axios.get('/test', { test: 1 }, { axios.get(
headers: { "/user",
'Content-Type': 'application/json; charset=utf-8' {
id: 1,
},
{
headers: {
"Content-Type": "application/json; charset=utf-8",
},
} }
}); );
// 发送 POST 请求 // 发送 POST 请求
axios.post('/test'); axios.post("/user");
// 携带数据 // 携带数据
axios.post('/test', { test: 1 }); axios.post("/user", {
id: 1,
});
// 携带额外配置 // 携带额外配置
axios.post('/test', { test: 1 }, { axios.post(
headers: { "/user",
'Content-Type': 'application/json; charset=utf-8' {
id: 1,
},
{
headers: {
"Content-Type": "application/json; charset=utf-8",
},
} }
}); );
``` ```
## 配置`config` ## 配置`config`
非全平台兼容的属性只会在平台支持的情况下生效。 非全平台兼容的属性只会在平台支持的情况下生效。
|参数|类型|默认值|说明|全平台兼容| | 参数 | 类型 | 默认值 | 说明 | 全平台兼容 |
|:-|:-|:-|:-|:-| | :---------------- | :------------------------ | :------------------------------------------------------------------------------------ | :----------------- | :--------- |
|adapter|Function|[查看](https://github.com/early-autumn/axios-miniprogram/blob/master/src/defaults.ts)|自定义适配器|是| | adapter | Function | [查看](https://github.com/early-autumn/axios-miniprogram/blob/master/src/defaults.ts) | 自定义适配器 | |
|baseURL|String| |基础地址|是| | baseURL | String | | 基础地址 | |
|url|String| |请求地址|是| | url | String | | 请求地址 | |
|method|String|get|请求方法| | | method | String | get | 请求方法 | |
|params|Object| |请求参数|是| | params | Object | | 请求参数 | |
|data|String/Object/ArrayBuffer| |请求数据|是| | data | String/Object/ArrayBuffer | | 请求数据 | |
|headers|Object|[查看](https://github.com/early-autumn/axios-miniprogram/blob/master/src/defaults.ts)|请求头|是| | headers | Object | [查看](https://github.com/early-autumn/axios-miniprogram/blob/master/src/defaults.ts) | 请求头 | |
|validateStatus|Function|[查看](https://github.com/early-autumn/axios-miniprogram/blob/master/src/defaults.ts)|自定义合法状态码|是| | validateStatus | Function | [查看](https://github.com/early-autumn/axios-miniprogram/blob/master/src/defaults.ts) | 自定义合法状态码 | |
|paramsSerializer|Function| |自定义参数序列化|是| | paramsSerializer | Function | | 自定义参数序列化 | |
|transformRequest|Function/Array<.Function>| |自定义转换请求数据|是| | transformRequest | Function/Array<.Function> | | 自定义转换请求数据 | |
|transformResponse|Function/Array<.Function>| |自定义转换响应数据|是| | transformResponse | Function/Array<.Function> | | 自定义转换响应数据 | |
|errorHandler|Function| |自定义错误处理|是| | errorHandler | Function | | 自定义错误处理 | |
|cancelToken|Object| |取消令牌|是| | cancelToken | Object | | 取消令牌 | |
|timeout|Number|10000|超时时间| | | timeout | Number | 10000 | 超时时间 | |
|dataType|String|json|响应数据格式|是| | dataType | String | json | 响应数据格式 | |
|responseType|String|text|响应数据类型|是| | responseType | String | text | 响应数据类型 | |
|enableHttp2|Boolean|false|开启 http2| | | enableHttp2 | Boolean | false | 开启 http2 | |
|enableQuic|Boolean|false|开启 quic| | | enableQuic | Boolean | false | 开启 quic | |
|enableCache|Boolean|false|开启 cache| | | enableCache | Boolean | false | 开启 cache | |
|sslVerify|Boolean|true|验证 ssl 证书| | | sslVerify | Boolean | true | 验证 ssl 证书 | |
#### `config.method`的合法值 #### `config.method`的合法值
可以使用大写,也可以使用小写。 可以使用大写,也可以使用小写。
|值|说明|全平台兼容| | | 说明 | 全平台兼容 |
|:-|:-|:-| | :------ | :--- | :--------- |
|OPTIONS| | | | OPTIONS | | |
|GET| |是| | GET | | |
|HEAD| | | | HEAD | | |
|POST| |是| | POST | | |
|PUT| |是| | PUT | | |
|DELETE| |是| | DELETE | | |
|TRACE| | | | TRACE | | |
|CONNECT| | | | CONNECT | | |
#### `config.dataType`的合法值 #### `config.dataType`的合法值
|值|说明|全平台兼容| | | 说明 | 全平台兼容 |
|:-|:-|:-| | :--- | :--------------------------------------------------------- | :--------- |
|json|返回的数据为 JSON返回后会对返回的数据进行一次 JSON.parse|是| | json | 返回的数据为 JSON返回后会对返回的数据进行一次 JSON.parse | |
|其他|不对返回的内容进行 JSON.parse|是| | 其他 | 不对返回的内容进行 JSON.parse | |
#### `config.responseType`的合法值 #### `config.responseType`的合法值
|值|说明|全平台兼容| | | 说明 | 全平台兼容 |
|:-|:-|:-| | :---------- | :----------------------- | :--------- |
|text|响应的数据为文本|是| | text | 响应的数据为文本 | |
|arraybuffer|响应的数据为 ArrayBuffer|是| | arraybuffer | 响应的数据为 ArrayBuffer | |
#### 自定义合法状态码`config.validateStatus` #### 自定义合法状态码`config.validateStatus`
可以让请求按照您的要求成功或者失败。 可以让请求按照您的要求成功或者失败。
```typescript ```typescript
axios('/test', { axios("/user", {
validateStatus: function validateStatus(status) { validateStatus: function validateStatus(status) {
// 这样,状态码在 200 到 400 之间都是请求成功 // 这样,状态码在 200 到 400 之间都是请求成功
return status >= 200 && status < 400; return status >= 200 && status < 400;
} },
}); });
``` ```
@ -200,10 +229,12 @@ axios('/test', {
可以使用自己的规则去序列化参数。 可以使用自己的规则去序列化参数。
```typescript ```typescript
axios('/test', { axios("/user", {
paramsSerializer: function paramsSerializer(params) { paramsSerializer: function paramsSerializer(params) {
return qs.stringify(params, {arrayFormat: 'brackets'}); return qs.stringify(params, {
} arrayFormat: "brackets",
});
},
}); });
``` ```
@ -212,15 +243,19 @@ axios('/test', {
可以在请求发出之前转换请求数据,在请求成功之后转换响应数据。 可以在请求发出之前转换请求数据,在请求成功之后转换响应数据。
```typescript ```typescript
axios('/test', { axios("/user", {
transformRequest: [function transformRequest(data, headers) { transformRequest: [
// 转换请求数据 function transformRequest(data, headers) {
return data; // 转换请求数据
}], return data;
transformResponse: [function transformResponse(data) { },
// 转换响应数据 ],
return data; transformResponse: [
}], function transformResponse(data) {
// 转换响应数据
return data;
},
],
}); });
``` ```
@ -232,24 +267,24 @@ axios('/test', {
axios.defaults.errorHandler = function errorHandler(error) { axios.defaults.errorHandler = function errorHandler(error) {
// 做一些想做的事情 // 做一些想做的事情
return Promise.reject(error); return Promise.reject(error);
} };
const instance = axios.create({ const instance = axios.create({
errorHandler: function errorHandler(error) { errorHandler: function errorHandler(error) {
// 做一些想做的事情 // 做一些想做的事情
return Promise.reject(error); return Promise.reject(error);
} },
}); });
``` ```
也可以发送请求时通过自定义配置传入。 也可以发送请求时通过自定义配置传入。
```typescript ```typescript
axios('/test', { axios("/user", {
errorHandler: function errorHandler(error) { errorHandler: function errorHandler(error) {
// 做一些想做的事情 // 做一些想做的事情
return Promise.reject(error); return Promise.reject(error);
} },
}); });
``` ```
@ -287,7 +322,7 @@ axios.defaults.adapter = function adapter(adapterConfig) {
// 成功的回调函数 // 成功的回调函数
success, success,
// 失败的回调函数 // 失败的回调函数
fail fail,
} = adapterConfig; } = adapterConfig;
// 在 adapterConfig 中选择您需要的参数发送请求 // 在 adapterConfig 中选择您需要的参数发送请求
@ -297,9 +332,9 @@ axios.defaults.adapter = function adapter(adapterConfig) {
data, data,
header, header,
success, success,
fail fail,
}); });
} };
// 如果 adapterConfig 的数据结构适用于当前平台,则可以。 // 如果 adapterConfig 的数据结构适用于当前平台,则可以。
axios.defaults.adapter = wx.request; axios.defaults.adapter = wx.request;
@ -310,9 +345,10 @@ axios.defaults.adapter = wx.request;
##### 全局默认配置`axios.defaults` ##### 全局默认配置`axios.defaults`
```typescript ```typescript
axios.defaults.baseURL = 'https://www.xxx.com'; axios.defaults.baseURL = "https://www.api.com";
axios.defaults.headers.common['Accept'] = 'application/json, test/plain, */*'; axios.defaults.headers.common["Accept"] = "application/json, test/plain, */*";
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'; axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded; charset=utf-8";
``` ```
##### 自定义实例默认配置 ##### 自定义实例默认配置
@ -321,24 +357,26 @@ axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded
```typescript ```typescript
const instance = axios.create({ const instance = axios.create({
baseURL: 'https://www.xxx.com', baseURL: "https://www.api.com",
headers: { headers: {
common: { common: {
'Accept': 'application/json, test/plain, */*' Accept: "application/json, test/plain, */*",
}, },
post: { post: {
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
} },
} },
}); });
``` ```
也可以创建后修改。 也可以创建后修改。
```typescript ```typescript
instance.defaults.baseURL = 'https://www.xxx.com'; instance.defaults.baseURL = "https://www.api.com";
instance.defaults.headers.common['Accept'] = 'application/json, test/plain, */*'; instance.defaults.headers.common["Accept"] =
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'; "application/json, test/plain, */*";
instance.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded; charset=utf-8";
``` ```
##### 配置优先顺序 ##### 配置优先顺序
@ -349,63 +387,64 @@ instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlenco
非全平台兼容的属性只会在平台支持的情况下生效。 非全平台兼容的属性只会在平台支持的情况下生效。
|属性|类型|说明|全平台兼容| | 属性 | 类型 | 说明 | 全平台兼容 |
|:-|:-|:-|:-| | :--------- | :------------------------ | :------------------------------------------- | :--------- |
|status|Number|状态码|是| | status | Number | 状态码 | 是 |
|statusText|String|状态文本|是| | statusText | String | 状态文本 | 是 |
|data|String/Object/ArrayBuffer|开发者服务器返回的数据|是| | data | String/Object/ArrayBuffer | 开发者服务器返回的数据 | 是 |
|headers|Object|响应头|是| | headers | Object | 响应头 | 是 |
|config|Object|Axios 请求配置|是| | config | Object | Axios 请求配置 | 是 |
|cookies|Array<.String>|开发者服务器返回的 cookies格式为字符串数组| | | cookies | Array<.String> | 开发者服务器返回的 cookies格式为字符串数组 | |
|profile|Object|网络请求过程中一些关键时间点的耗时信息| | | profile | Object | 网络请求过程中一些关键时间点的耗时信息 | |
## API ## API
### `axios.interceptors` ### `axios.interceptors`
可以先拦截请求或响应然后再由then或catch处理。 可以先拦截请求或响应,然后再由 then catch 处理。
```typescript ```typescript
// 添加请求拦截器 // 添加请求拦截器
axios.interceptors.request.use(function (config) { axios.interceptors.request.use(
// 在发送请求之前做些什么 function(config) {
console.log('request'); // 在发送请求之前做些什么
return config; return config;
}, function (error) { },
//处理请求错误 function(error) {
return Promise.reject(error); //处理请求错误
}); return Promise.reject(error);
}
);
// 添加响应拦截器 // 添加响应拦截器
axios.interceptors.response.use(function (response) { axios.interceptors.response.use(
// 请求成功后做些什么 function(response) {
console.log('response'); // 请求成功后做些什么
return response; return response;
}, function (error) { },
// 处理响应错误 function(error) {
return Promise.reject(error); // 处理响应错误
}); return Promise.reject(error);
}
axios('/test').then(function (response){ );
console.log('ok');
});
// log 'request' 'response' 'ok'
``` ```
如果以后需要删除拦截器,则可以。 如果以后需要删除拦截器,则可以。
```typescript ```typescript
const myInterceptor = axios.interceptors.request.use(function () {/*...*/}); const myInterceptor = axios.interceptors.request.use(function() {
// 在发送请求之前做些什么
});
axios.interceptors.request.eject(myInterceptor); axios.interceptors.request.eject(myInterceptor);
``` ```
还可以将拦截器添加到`axios`的`自定义实例`中。 还可以将拦截器添加到`axios`的`自定义实例`中。
```typescript ```typescript
const myInterceptor = axios.interceptors.request.use(function () {/*...*/}); const myInterceptor = instance.interceptors.request.use(function() {
axios.interceptors.request.eject(myInterceptor); // 在发送请求之前做些什么
});
instance.interceptors.request.eject(myInterceptor);
``` ```
### `axios.CancelToken` ### `axios.CancelToken`
@ -415,13 +454,13 @@ axios.interceptors.request.eject(myInterceptor);
```typescript ```typescript
let cancel; let cancel;
axios('/test', { axios("/api", {
cancelToken: new axios.CancelToken(function (c){ cancelToken: new axios.CancelToken(function(c) {
cancel = c; cancel = c;
}) }),
}); });
cancel('取消请求'); cancel("取消请求");
``` ```
还可以使用`CancelToken.source`工厂方法创建`CancelToken`。 还可以使用`CancelToken.source`工厂方法创建`CancelToken`。
@ -429,11 +468,11 @@ cancel('取消请求');
```typescript ```typescript
const source = axios.CancelToken.source(); const source = axios.CancelToken.source();
axios('/test', { axios("/api", {
cancelToken: source.token cancelToken: source.token,
}); });
source.cancel('取消请求'); source.cancel("取消请求");
``` ```
### `axios.isCancel` ### `axios.isCancel`
@ -441,8 +480,8 @@ source.cancel('取消请求');
可以判断当前错误是否来自取消请求 可以判断当前错误是否来自取消请求
```typescript ```typescript
axios('/test').catch((error) => { axios("/user").catch((error) => {
if(axios.isCancel(error)){ if (axios.isCancel(error)) {
// 请求被取消了 // 请求被取消了
} }
}); });
@ -453,11 +492,13 @@ axios('/test').catch((error) => {
根据配置中的`url`和`params`生成一个`URI`。 根据配置中的`url`和`params`生成一个`URI`。
```typescript ```typescript
// uri === '/test?id=1'
const uri = axios.getUri({ const uri = axios.getUri({
url: '/test', url: "/user",
params: { id: 1 } params: {
id: 1,
},
}); });
// '/user?id=1'
``` ```
### `axios.create(defaults)` ### `axios.create(defaults)`
@ -467,20 +508,16 @@ const uri = axios.getUri({
`自定义实例`拥有和`axios`相同的调用方式和请求方法的别名。 `自定义实例`拥有和`axios`相同的调用方式和请求方法的别名。
```typescript ```typescript
axios.defaults.baseURL = 'https://www.xxx.com'; axios.defaults.baseURL = "https://www.api.com";
const instance = axios.create({ const instance = axios.create({
params: { params: {
id: 1 id: 1,
} },
}); });
// 最终请求的 URL 是这样的 => https://www.xxx.com/test?id=1 instance("/user");
// https://www.xxx.com 来自 axios.defaults.baseURL // 'https://www.api.com/user?id=1'
// /test 来自传入的 '/test'
// id=1 来自 instance.defaults.params
instance('/test');
instance.get('/test');
``` ```
### `axios.Axios` ### `axios.Axios`
@ -490,22 +527,23 @@ instance.get('/test');
直接实例化`axios.Axios`可以得到一个`原始实例`,不能当函数调用,传入的自定义配置就是`原始实例`的默认配置,而不会像`axios.create(defaults)`一样去合并`axios`中的默认配置。 直接实例化`axios.Axios`可以得到一个`原始实例`,不能当函数调用,传入的自定义配置就是`原始实例`的默认配置,而不会像`axios.create(defaults)`一样去合并`axios`中的默认配置。
```typescript ```typescript
axios.defaults.baseURL = 'https://www.xxx.com';
const instance = new axios.Axios({ const instance = new axios.Axios({
params: { value: 123 } beseURL: "https://www.api.com",
params: {
id: 1,
},
}); });
// 最终请求的 URL 是这样的 => /test?value=123 instance.get("/user");
// /test 来自传入的 '/test' // 'https://www.api.com/user?id=1'
// value=123 来自 instance.defaults.params
instance.get('/test');
``` ```
## 执行流程 ## 执行流程
```typescript ```typescript
axios('/test').then().catch(); axios("/user")
.then()
.catch();
// 请求成功 // 请求成功
// axios => axios.interceptors.request => config.transformRequest => config.paramsSerializer => config.adapter => config.validateStatus => config.transformResponse => axios.interceptors.response => then // axios => axios.interceptors.request => config.transformRequest => config.paramsSerializer => config.adapter => config.validateStatus => config.transformResponse => axios.interceptors.response => then

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
import { Adapter, Platform } from './types'; import { Adapter, Platform } from './types';
import { isUndefined } from './helpers/utils';
// uniapp // uniapp
declare let uni: Platform; declare let uni: Platform;
@ -28,7 +29,7 @@ export default function adaptive(): Adapter | undefined {
let adapter: Adapter | undefined; let adapter: Adapter | undefined;
while (stack.length !== 0 && adapter === void 0) { while (stack.length !== 0 && isUndefined(adapter)) {
try { try {
adapter = (stack.shift() as () => Adapter)(); adapter = (stack.shift() as () => Adapter)();
} catch (err) {} } catch (err) {}

View File

@ -1,5 +1,5 @@
import { Headers, AxiosRequestConfig } from '../types'; import { Headers, AxiosRequestConfig } from '../types';
import { omit } from '../helpers/utils'; import { isUndefined, omit } from '../helpers/utils';
import { methodToLowercase } from './transformMethod'; import { methodToLowercase } from './transformMethod';
/** /**
@ -10,7 +10,7 @@ import { methodToLowercase } from './transformMethod';
export default function flattenHeaders(config: AxiosRequestConfig): Headers { export default function flattenHeaders(config: AxiosRequestConfig): Headers {
const { headers } = config; const { headers } = config;
if (headers === void 0) { if (isUndefined(headers)) {
return {}; return {};
} }

View File

@ -79,9 +79,9 @@ function deepMergeConfig(
) { ) {
keys.forEach((key) => { keys.forEach((key) => {
if (isPlainObject(config2[key])) { if (isPlainObject(config2[key])) {
config[key] = deepMerge(config1[key] ?? {}, config2[key] as AnyObject); config[key] = deepMerge<AnyObject>(config1[key] ?? {}, config2[key] as AnyObject);
} else if (isPlainObject(config1[key])) { } else if (isPlainObject(config1[key])) {
config[key] = deepMerge(config1[key] as AnyObject); config[key] = deepMerge<AnyObject>(config1[key] as AnyObject);
} }
}); });
} }

View File

@ -1,4 +1,5 @@
import { AxiosRequestConfig, AxiosResponse, Response } from '../types'; import { AxiosRequestConfig, AxiosResponse, Response } from '../types';
import { isString, isUndefined } from '../helpers/utils';
import transformRequest from './transformRequest'; import transformRequest from './transformRequest';
import transformResponse from './transformResponse'; import transformResponse from './transformResponse';
import createError from './createError'; import createError from './createError';
@ -20,14 +21,14 @@ export default function request(config: AxiosRequestConfig): Promise<AxiosRespon
* @param response Axios * @param response Axios
*/ */
function catchError(message: any, response?: AxiosResponse): void { function catchError(message: any, response?: AxiosResponse): void {
if (typeof message !== 'string') { if (!isString(message)) {
message = '配置不正确或者网络异常'; message = message.fail;
} }
reject(createError(message, config, requestConfig, response)); reject(createError(message, config, requestConfig, response));
} }
if (adapter === void 0) { if (isUndefined(adapter)) {
catchError('平台适配失败,您需要参阅文档使用自定义适配器手动适配当前平台'); catchError('平台适配失败,您需要参阅文档使用自定义适配器手动适配当前平台');
return; return;
@ -41,7 +42,7 @@ export default function request(config: AxiosRequestConfig): Promise<AxiosRespon
function handleResponse(res: Response): void { function handleResponse(res: Response): void {
const response = transformResponse(res, config); const response = transformResponse(res, config);
if (config.validateStatus === void 0 || config.validateStatus(response.status)) { if (isUndefined(config.validateStatus) || config.validateStatus(response.status)) {
resolve(response); resolve(response);
} else { } else {
catchError(`请求失败,状态码为 ${response.status}`, response); catchError(`请求失败,状态码为 ${response.status}`, response);
@ -57,9 +58,9 @@ export default function request(config: AxiosRequestConfig): Promise<AxiosRespon
// 如果存在取消令牌 // 如果存在取消令牌
// 则调用取消令牌里的 listener 监听用户的取消操作 // 则调用取消令牌里的 listener 监听用户的取消操作
if (cancelToken !== void 0) { if (!isUndefined(cancelToken)) {
cancelToken.listener.then(function onCanceled(reason): void { cancelToken.listener.then(function onCanceled(reason): void {
if (task !== void 0) { if (!isUndefined(task)) {
task.abort(); task.abort();
} }

View File

@ -1,4 +1,5 @@
import { Data, Headers, TransformData } from '../types'; import { Data, Headers, TransformData } from '../types';
import { isUndefined } from '../helpers/utils';
/** /**
* *
@ -12,7 +13,7 @@ export default function transformData(
headers: Headers, headers: Headers,
transforms?: TransformData | TransformData[] transforms?: TransformData | TransformData[]
): Data { ): Data {
if (transforms === void 0) { if (isUndefined(transforms)) {
return data; return data;
} }

View File

@ -1,5 +1,5 @@
import { AnyObject, Params } from '../types'; import { AnyObject, Params } from '../types';
import { encode, isPlainObject, isDate } from './utils'; import { encode, isPlainObject, isDate, isUndefined, isNull } from './utils';
/** /**
* *
@ -36,7 +36,7 @@ function paramsSerialization(params: AnyObject): string {
const parts: string[] = []; const parts: string[] = [];
Object.entries(params).forEach(function encodeKeyValue([key, value]): void { Object.entries(params).forEach(function encodeKeyValue([key, value]): void {
if (value === null || value === void 0 || value !== value) { if (isNull(value) || isUndefined(value) || value !== value) {
return; return;
} }

View File

@ -1,4 +1,4 @@
import { AnyObject } from '../types'; import { AnyObject, ObjectTree } from '../types';
const _toString = Object.prototype.toString; const _toString = Object.prototype.toString;
@ -19,21 +19,40 @@ export function encode(str: string): string {
} }
/** /**
* * Date
*
* @param date
*/ */
export function isDate(date: unknown): date is Date { export function isDate(date: unknown): date is Date {
return _toString.call(date) === '[object Date]'; return _toString.call(date) === '[object Date]';
} }
/** /**
* *
*
* @param obj
*/ */
export function isPlainObject(obj: unknown): obj is Record<string, unknown> { export function isPlainObject<T = never>(
return _toString.call(obj) === '[object Object]'; value: unknown
): value is [T] extends never[] ? AnyObject : T {
return _toString.call(value) === '[object Object]';
}
/**
* undefined
*/
export function isUndefined(value: unknown): value is undefined {
return typeof value === 'undefined';
}
/**
*
*/
export function isString(value: unknown): value is number {
return typeof value === 'string';
}
/**
* Null
*/
export function isNull(value: unknown): value is null {
return value === null;
} }
/** /**
@ -41,19 +60,19 @@ export function isPlainObject(obj: unknown): obj is Record<string, unknown> {
* *
* @param objs n * @param objs n
*/ */
export function deepMerge(...objs: Record<string, any>[]): Record<string, any> { export function deepMerge<T = never>(...objs: ObjectTree[]): [T] extends never[] ? ObjectTree : T {
const result: Record<string, any> = {}; const result: ObjectTree = {};
function assignValue(key: string, val: any) { function assignValue(key: string, val: unknown) {
// 如果当前结果和当前值都为普通对象 // 如果当前结果和当前值都为普通对象
// 递归进行深度合并 // 递归进行深度合并
if (isPlainObject(result[key]) && isPlainObject(val)) { if (isPlainObject(result[key]) && isPlainObject(val)) {
result[key] = deepMerge(result[key], val); result[key] = deepMerge(result[key] as ObjectTree, val as ObjectTree);
} }
// 如果只有当前值为普通对象 // 如果只有当前值为普通对象
// 直接深拷贝当前值 // 直接深拷贝当前值
else if (isPlainObject(val)) { else if (isPlainObject(val)) {
result[key] = deepMerge({}, val); result[key] = deepMerge({}, val as ObjectTree);
} }
// 如果都不是普通对象 // 如果都不是普通对象
// 直接赋值 // 直接赋值
@ -62,13 +81,13 @@ export function deepMerge(...objs: Record<string, any>[]): Record<string, any> {
} }
} }
objs.forEach(function assignObj(obj: Record<string, any>): void { objs.forEach(function assignObj(obj: ObjectTree): void {
Object.entries(obj).forEach(function assignKey([key, value]) { Object.entries(obj).forEach(function ([key, value]) {
assignValue(key, value); assignValue(key, value);
}); });
}); });
return result; return result as [T] extends never[] ? ObjectTree : T;
} }
/** /**

View File

@ -191,7 +191,7 @@ export declare interface AdapterRequestTask {
* *
*/ */
export declare interface Adapter { export declare interface Adapter {
(config: AdapterRequestConfig): AdapterRequestTask | void; (config: AdapterRequestConfig): AdapterRequestTask | undefined;
} }
/** /**
@ -318,6 +318,8 @@ export declare interface AxiosRequestConfig {
* ssl * ssl
*/ */
sslVerify?: boolean; sslVerify?: boolean;
[key: string]: unknown;
} }
/** /**
@ -734,3 +736,7 @@ export declare interface AxiosInstance extends AxiosBaseInstance {
*/ */
isCancel: (value: any) => boolean; isCancel: (value: any) => boolean;
} }
export interface ObjectTree<T = unknown> {
[key: string]: T | ObjectTree<T>;
}

5
types/adaptive.d.ts vendored
View File

@ -1,5 +0,0 @@
import { Adapter } from './types';
/**
*
*/
export default function adaptive(): Adapter | undefined;

6
types/axios.d.ts vendored
View File

@ -1,6 +0,0 @@
import { AxiosInstance } from './types';
/**
* Axios
*/
declare const axios: AxiosInstance;
export default axios;

View File

@ -1,9 +0,0 @@
import { Cancel } from '../types';
export default class CancelClass implements Cancel {
message?: string | undefined;
/**
* @param message
*/
constructor(message?: string | undefined);
toString(): string;
}

View File

@ -1,23 +0,0 @@
import { CancelToken, CancelExecutor, CancelTokenSource } from '../types';
import Cancel from './Cancel';
export default class CancelTokenClass implements CancelToken {
/**
*
*/
private _reason?;
listener: Promise<Cancel>;
constructor(executor: CancelExecutor);
throwIfRequested(): void;
/**
* CancelTokenSource
*
* CancelTokenSource.token CancelToken
*
* CancelTokenSource.cancel CancelAction
*
* CancelTokenSource.cancel('这里可以填写您的错误信息')
*
* CancelTokenSource.token
*/
static source(): CancelTokenSource;
}

View File

@ -1,7 +0,0 @@
import Cancel from './Cancel';
/**
*
*
* @param value
*/
export default function isCancel(value: unknown): value is Cancel;

37
types/core/Axios.d.ts vendored
View File

@ -1,37 +0,0 @@
import { Params, Data, Interceptors, AxiosRequestConfig, AxiosResponse, Axios } from '../types';
export default class AxiosClass implements Axios {
defaults: AxiosRequestConfig;
interceptors: Interceptors;
/**
* @param defaults
*/
constructor(defaults?: AxiosRequestConfig);
getUri(config: AxiosRequestConfig): string;
request<T extends Data>(config: AxiosRequestConfig): Promise<AxiosResponse<T>>;
options<T extends Data>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
get<T extends Data>(url: string, params?: Params, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
head<T extends Data>(url: string, params?: Params, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
post<T extends Data>(url: string, data?: Data, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
put<T extends Data>(url: string, data?: Data, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
delete<T extends Data>(url: string, params?: Params, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
trace<T extends Data>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
connect<T extends Data>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
/**
* HTTP
*
* @param method
* @param url
* @param params
* @param config
*/
private _requestMethodWithoutParams;
/**
* HTTP
*
* @param method
* @param url
* @param data
* @param config
*/
private _requestMethodWithoutData;
}

View File

@ -1,17 +0,0 @@
import { InterceptorResolved, InterceptorRejected, InterceptorExecutor, InterceptorManager } from '../types';
/**
*
*/
export default class InterceptorManagerClass<T> implements InterceptorManager<T> {
/**
* id
*/
private _id;
/**
*
*/
private _interceptors;
use(resolved: InterceptorResolved<T>, rejected?: InterceptorRejected): number;
eject(id: number): void;
forEach(executor: InterceptorExecutor<T>, reverse?: 'reverse'): void;
}

View File

@ -1,12 +0,0 @@
import { AxiosRequestConfig, RequestConfig, AxiosResponse, AxiosError } from '../types';
/**
* AxiosError
*
* AxiosError
*
* @param message
* @param config Axios
* @param request
* @param response Axios
*/
export default function createError(message: string, config: AxiosRequestConfig, request: RequestConfig, response?: AxiosResponse): AxiosError;

View File

@ -1,7 +0,0 @@
import { AxiosRequestConfig, AxiosResponse } from '../types';
/**
*
*
* @param config Axios
*/
export default function dispatchRequest(config: AxiosRequestConfig): Promise<AxiosResponse>;

View File

@ -1,7 +0,0 @@
import { Headers, AxiosRequestConfig } from '../types';
/**
*
*
* @param config Axios
*/
export default function flattenHeaders(config: AxiosRequestConfig): Headers;

View File

@ -1,8 +0,0 @@
import { AxiosRequestConfig } from '../types';
/**
* Axios
*
* @param config1 Axios 1
* @param config2 Axios 2
*/
export default function mergeConfig(config1?: AxiosRequestConfig, config2?: AxiosRequestConfig): AxiosRequestConfig;

View File

@ -1,7 +0,0 @@
import { AxiosRequestConfig, AxiosResponse } from '../types';
/**
*
*
* @param config Axios
*/
export default function request(config: AxiosRequestConfig): Promise<AxiosResponse>;

View File

@ -1,9 +0,0 @@
import { Data, Headers, TransformData } from '../types';
/**
*
*
* @param data /
* @param headers /
* @param transforms /
*/
export default function transformData(data: Data, headers: Headers, transforms?: TransformData | TransformData[]): Data;

View File

@ -1,13 +0,0 @@
import { AliasMethod, AdapterMethod, Method } from '../types';
/**
*
*
* @param config Axios
*/
export declare function methodToLowercase(method?: Method): AliasMethod;
/**
*
*
* @param config Axios
*/
export declare function methodToUppercase(method?: Method): AdapterMethod;

View File

@ -1,9 +0,0 @@
import { AxiosRequestConfig, RequestConfig } from '../types';
/**
* Axios
*
*
*
* @param config Axios
*/
export default function transformRequest(config: AxiosRequestConfig): RequestConfig;

View File

@ -1,10 +0,0 @@
import { AxiosRequestConfig, AxiosResponse, Response } from '../types';
/**
* Axios
*
*
*
* @param response
* @param config Axios
*/
export default function transformResponse(response: Response, config: AxiosRequestConfig): AxiosResponse;

3
types/defaults.d.ts vendored
View File

@ -1,3 +0,0 @@
import { AxiosRequestConfig } from './types';
declare const defaults: AxiosRequestConfig;
export default defaults;

View File

@ -1,16 +0,0 @@
import { AnyObject, Params } from '../types';
/**
*
*
* @param params
*/
declare function paramsSerialization(params: AnyObject): string;
/**
* URL
*
* @param url
* @param params
* @param paramsSerializer
*/
export default function buildURL(url: string, params?: Params, paramsSerializer?: typeof paramsSerialization): string;
export {};

View File

@ -1,6 +0,0 @@
/**
* baseURL url URL
*
* combineURL('1/2///','////3/4') => '1/2/3/4'
*/
export default function combineURL(baseURL: string, url: string): string;

View File

@ -1,8 +0,0 @@
/**
* URL
*
* xxx:// 或者 "//" 开头, 视为绝对地址
*
* @param url URL
*/
export default function isAbsoluteURL(url: string): boolean;

View File

@ -1,39 +0,0 @@
import { AnyObject } from '../types';
/**
*
*
* @param str
*/
export declare function encode(str: string): string;
/**
*
*
* @param date
*/
export declare function isDate(date: unknown): date is Date;
/**
*
*
* @param obj
*/
export declare function isPlainObject(obj: unknown): obj is Record<string, unknown>;
/**
*
*
* @param objs n
*/
export declare function deepMerge(...objs: Record<string, any>[]): Record<string, any>;
/**
*
*
* @param obj
* @param keys key
*/
export declare function pick<T extends AnyObject, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;
/**
*
*
* @param obj
* @param keys key
*/
export declare function omit<T extends AnyObject, K extends keyof T>(obj: T, ...keys: K[]): Omit<T, K>;

3
types/index.d.ts vendored
View File

@ -1,3 +0,0 @@
import axios from './axios';
export * from './types';
export default axios;

596
types/types.d.ts vendored
View File

@ -1,596 +0,0 @@
/**
*
*/
export declare interface AnyObject<T extends any = any> {
[x: string]: T;
}
/**
*
*/
export declare type AdapterMethod = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT';
/**
*
*/
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;
/**
* Axios
*/
export declare type Data = string | AnyObject | ArrayBuffer;
/**
* Axios
*/
export declare interface Headers extends Partial<Record<'common' | AliasMethod, AnyObject<string>>> {
/**
*
*/
[x: string]: AnyObject<string> | string | undefined;
}
/**
*
*/
export declare interface RequestConfig {
/**
*
*/
url: string;
/**
* HTTP
*/
method: AdapterMethod;
/**
*
*/
data: Data;
/**
* headers
*/
header: AnyObject;
/**
* header
*/
headers: AnyObject;
/**
*
*/
dataType?: 'json' | '其他';
/**
*
*/
responseType?: 'text' | 'arraybuffer';
/**
*
*/
timeout?: number;
/**
* http2
*/
enableHttp2?: boolean;
/**
* quic
*/
enableQuic?: boolean;
/**
* cache
*/
enableCache?: boolean;
/**
* ssl
*/
sslVerify?: boolean;
}
/**
*
*/
export declare interface Response {
/**
*
*/
statusCode?: number;
/**
*
*/
status?: number;
/**
* Headers
*/
header?: AnyObject;
/**
* Headers
*/
headers?: Headers;
/**
*
*/
data: Data;
/**
* cookies
*/
cookies?: string[];
/**
*
*/
profile?: AnyObject;
}
/**
*
*/
export declare interface AdapterRequestConfig extends RequestConfig {
/**
*
*/
success: (res: Response) => void;
/**
*
*/
fail: (err: unknown) => void;
}
/**
*
*/
export declare interface AdapterRequestTask {
/**
*
*/
abort(): void;
}
/**
*
*/
export declare interface Adapter {
(config: AdapterRequestConfig): AdapterRequestTask | void;
}
/**
*
*/
export declare interface Platform {
request: Adapter;
}
/**
*
*/
export declare interface TransformData {
(data: Data, headers: Headers): Data;
}
/**
*
*/
export declare interface ErrorHandler {
(error: any): Promise<any> | any;
}
/**
* Axios
*/
export declare interface AxiosRequestConfig {
/**
*
*/
adapter?: Adapter;
/**
*
*/
baseURL?: string;
/**
*
*/
url?: string;
/**
*
*/
method?: Method;
/**
*
*/
params?: Params;
/**
*
*/
data?: Data;
/**
*
*/
headers?: Headers;
/**
*
*/
validateStatus?: (status: number) => boolean;
/**
*
*/
paramsSerializer?: (params?: AnyObject) => string;
/**
*
*/
transformRequest?: TransformData | TransformData[];
/**
*
*/
transformResponse?: TransformData | TransformData[];
/**
*
*/
errorHandler?: ErrorHandler;
/**
*
*/
cancelToken?: CancelToken;
/**
*
*/
timeout?: number;
/**
*
*/
dataType?: 'json' | '其他';
/**
*
*/
responseType?: 'text' | 'arraybuffer';
/**
* http2
*/
enableHttp2?: boolean;
/**
* quic
*/
enableQuic?: boolean;
/**
* cache
*/
enableCache?: boolean;
/**
* ssl
*/
sslVerify?: boolean;
}
/**
* Axios
*/
export declare interface AxiosResponse<T extends Data = Data> {
/**
*
*/
status: number;
/**
*
*/
statusText: string;
/**
*
*/
data: T;
/**
*
*/
headers: Headers;
/**
* Axios
*/
config: AxiosRequestConfig;
/**
* cookies
*/
cookies?: string[];
/**
*
*/
profile?: AnyObject;
}
/**
*
*/
export declare interface InterceptorResolved<T = any> {
(value: T): Promise<T> | T;
}
/**
*
*/
export declare interface InterceptorRejected {
(error: any): any;
}
/**
*
*/
export declare interface Interceptor<T = any> {
/**
*
*/
resolved: InterceptorResolved<T>;
/**
*
*/
rejected?: InterceptorRejected;
}
/**
*
*/
export declare interface InterceptorExecutor<T = any> {
(interceptor: Interceptor<T>): void;
}
/**
*
*/
export declare interface InterceptorManager<T = any> {
[x: string]: any;
/**
*
*
* @param resolved
* @param rejected
*/
use(resolved: InterceptorResolved<T>, rejected?: InterceptorRejected): number;
/**
*
*
* @param id id
*/
eject(id: number): void;
/**
*
*
* @param executor
* @param reverse
*/
forEach(executor: InterceptorExecutor<T>, reverse?: 'reverse'): void;
}
/**
* Axios
*/
export declare interface Interceptors {
/**
* request
*/
request: InterceptorManager<AxiosRequestConfig>;
/**
* response
*/
response: InterceptorManager<AxiosResponse>;
}
/**
* Axios
*/
export declare interface Axios {
/**
*
*/
defaults: AxiosRequestConfig;
/**
* Axios
*/
interceptors: Interceptors;
/**
* url params URI
*
* @param config
*/
getUri(config: AxiosRequestConfig): string;
/**
* HTTP
*
* @param config
*/
request<T extends Data>(config: AxiosRequestConfig): Promise<AxiosResponse<T>>;
/**
* HTTP OPTIONS
*
* @param url
* @param config
*/
options<T extends Data>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
/**
* HTTP GET
*
* @param url
* @param params
* @param config
*/
get<T extends Data>(url: string, params?: Params, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
/**
* HTTP HEAD
*
* @param url
* @param params
* @param config
*/
head<T extends Data>(url: string, params?: Params, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
/**
* HTTP POST
*
* @param url
* @param data
* @param config
*/
post<T extends Data>(url: string, data?: Data, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
/**
* HTTP PUT
*
* @param url
* @param data
* @param config
*/
put<T extends Data>(url: string, data?: Data, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
/**
* HTTP DELETE
*
* @param url
* @param params
* @param config
*/
delete<T extends Data>(url: string, params?: Params, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
/**
* HTTP TRACE
*
* @param url
* @param config
*/
trace<T extends Data>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
/**
* HTTP CONNECT
*
* @param url
* @param config
*/
connect<T extends Data>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
}
/**
* Axios
*/
export declare interface AxiosConstructor {
new (config?: AxiosRequestConfig): Axios;
}
/**
* AxiosError Error
*/
export declare interface AxiosError extends Error {
/**
* Axios
*/
isAxiosError: boolean;
/**
*
*/
config: AxiosRequestConfig;
/**
*
*/
request: RequestConfig;
/**
* Axios
*/
response?: AxiosResponse;
}
/**
*
*/
export declare interface Cancel {
/**
*
*/
message?: string;
/**
*
*/
toString(): string;
}
/**
*
*/
export declare interface CancelConstructor {
new (message?: string): Cancel;
}
/**
*
*/
export declare interface CancelAction {
(message?: string): void;
}
/**
*
*/
export declare interface CancelExecutor {
(cancel: CancelAction): void;
}
/**
*
*/
export declare interface CancelToken {
/**
*
*/
listener: Promise<Cancel>;
/**
* ,
*/
throwIfRequested(): void;
}
/**
* source
*/
export declare interface CancelTokenSource {
/**
*
*/
token: CancelToken;
/**
*
*/
cancel: CancelAction;
}
/**
*
*/
export declare interface CancelTokenConstructor {
new (executor: CancelExecutor): CancelToken;
/**
* CancelTokenSource
*
* CancelTokenSource.token CancelToken
*
* CancelTokenSource.cancel CancelAction
*
* CancelTokenSource.cancel('这里可以填写您的错误信息')
*
* CancelTokenSource.token
*/
source(): CancelTokenSource;
}
/**
* Axios
*
* *
*/
export declare interface AxiosBaseInstance extends Axios {
/**
* HTTP
*
*
*
* @param config
*/
<T extends Data>(config: AxiosRequestConfig): Promise<AxiosResponse<T>>;
/**
* HTTP
*
*
*
* @param url
* @param config
*/
<T extends Data>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
}
/**
* Axios
*
* *
*
* *
*/
export declare interface AxiosInstance extends AxiosBaseInstance {
/**
* Axios
*
* @param defaults
*/
create(defaults?: AxiosRequestConfig): AxiosBaseInstance;
/**
* Axios
*/
Axios: AxiosConstructor;
/**
*
*/
CancelToken: CancelTokenConstructor;
/**
*
*
* @param value
*/
isCancel: (value: any) => boolean;
}