clear
parent
7e5f2c376c
commit
48658e7618
20
.babelrc
20
.babelrc
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [
|
|
||||||
"@babel/preset-typescript",
|
|
||||||
[
|
|
||||||
"@babel/preset-env",
|
|
||||||
{
|
|
||||||
"targets": {
|
|
||||||
"browsers": [
|
|
||||||
"ie >= 11"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"modules": false,
|
|
||||||
"loose": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"@babel/plugin-proposal-optional-chaining"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
/node_modules
|
|
||||||
/package
|
|
||||||
/types
|
|
||||||
/coverage
|
|
||||||
/rollup.config.js
|
|
27
.eslintrc
27
.eslintrc
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* @Author: early-autumn
|
|
||||||
* @Date: 2020-03-06 20:35:23
|
|
||||||
* @LastEditors: early-autumn
|
|
||||||
* @LastEditTime: 2020-04-17 12:39:07
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"extends": [
|
|
||||||
"plugin:@typescript-eslint/recommended",
|
|
||||||
"prettier/@typescript-eslint",
|
|
||||||
"plugin:prettier/recommended"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"@typescript-eslint",
|
|
||||||
"prettier"
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"node": true,
|
|
||||||
"es6": true
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
|
||||||
"@typescript-eslint/explicit-function-return-type": "off",
|
|
||||||
"@typescript-eslint/no-namespace": "off"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
/node_modules
|
|
||||||
/package
|
|
||||||
/package.zip
|
|
||||||
/types
|
|
||||||
/coverage
|
|
||||||
/yarn-error.log
|
|
10
.prettierrc
10
.prettierrc
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"printWidth": 120,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"singleQuote": true,
|
|
||||||
"semi": true,
|
|
||||||
"trailingComma": "es5",
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"arrowParens": "always",
|
|
||||||
"parser": "typescript"
|
|
||||||
}
|
|
11
.travis.yml
11
.travis.yml
|
@ -1,11 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js: stable
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- node_modules
|
|
||||||
install:
|
|
||||||
- npm install
|
|
||||||
script:
|
|
||||||
- npm run prettier
|
|
||||||
- npm run lint
|
|
||||||
- npm run coverage
|
|
21
LICENSE
21
LICENSE
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2020 初秋
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
514
README.md
514
README.md
|
@ -1,514 +0,0 @@
|
||||||
# axios-miniprogram
|
|
||||||
|
|
||||||
[](https://travis-ci.org/zjx0905/axios-miniprogram)
|
|
||||||
[](https://coveralls.io/github/zjx0905/axios-miniprogram?branch=master)
|
|
||||||
[](https://badge.fury.io/js/axios-miniprogram)
|
|
||||||
[](https://opensource.org/licenses/MIT)
|
|
||||||
|
|
||||||
## 安装
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ yarn add axios-miniprogram
|
|
||||||
```
|
|
||||||
|
|
||||||
或者
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm i axios-miniprogram
|
|
||||||
```
|
|
||||||
|
|
||||||
## 简介
|
|
||||||
|
|
||||||
小程序平台专用请求库,实现了 [axios](https://github.com/axios/axios) 大部分功能,用法只存在少许差异,如果您是 [axios](https://github.com/axios/axios) 的老用户,那么不需要学习就可以直接上手使用。
|
|
||||||
|
|
||||||
* 支持 微信小程序、支付宝小程序、百度小程序、字节跳动小程序、QQ 小程序、uniapp。
|
|
||||||
* 支持 `Typescript`,健全的类型系统,智能的 `IDE` 提示。
|
|
||||||
* 支持 `Promise`。
|
|
||||||
* 支持 拦截器。
|
|
||||||
* 支持 取消请求。
|
|
||||||
* 支持 自定义合法状态码。
|
|
||||||
* 支持 自定义参数序列化。
|
|
||||||
* 支持 自定义转换数据。
|
|
||||||
* 支持 自定义错误处理。
|
|
||||||
* 支持 自定义平台适配器
|
|
||||||
|
|
||||||
## 使用
|
|
||||||
|
|
||||||
### `axios(config)`
|
|
||||||
|
|
||||||
可以通过将相关配置传递给`axios`来发送请求。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// 发送 GET 请求
|
|
||||||
axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/test',
|
|
||||||
params: { test: 1 }
|
|
||||||
}).then((response) => {
|
|
||||||
// 请求成功后做些什么
|
|
||||||
}).catch((error) => {
|
|
||||||
// 请求失败后做些什么
|
|
||||||
});
|
|
||||||
|
|
||||||
// 发送 POST 请求
|
|
||||||
axios({
|
|
||||||
method: 'post',
|
|
||||||
url: '/test',
|
|
||||||
data: { test: 1 }
|
|
||||||
}).then((response) => {
|
|
||||||
// 请求成功后做些什么
|
|
||||||
}).catch((error) => {
|
|
||||||
// 请求失败后做些什么
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### `axios(url, config?)`
|
|
||||||
|
|
||||||
也可以通过直接把`url`传给`axios`来发送请求。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// 默认发送 GET 请求
|
|
||||||
axios('/test/xxx').then((response) => {
|
|
||||||
// 请求成功后做些什么
|
|
||||||
}).catch((error) => {
|
|
||||||
// 请求失败后做些什么
|
|
||||||
});
|
|
||||||
|
|
||||||
// 发送 POST 请求
|
|
||||||
axios('/test/xxx', { method: 'post' }).then((response) => {
|
|
||||||
// 请求成功后做些什么
|
|
||||||
}).catch((error) => {
|
|
||||||
// 请求失败后做些什么
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
还可以使用请求方法的别名来简化请求。
|
|
||||||
|
|
||||||
* ##### axios.request(config)
|
|
||||||
* ##### axios.options(url, config?)
|
|
||||||
* ##### axios.get(url, params?, config?)
|
|
||||||
* ##### axios.head(url, params?, config?)
|
|
||||||
* ##### axios.post(url, data?, config?)
|
|
||||||
* ##### axios.put(url, data?, config?)
|
|
||||||
* ##### axios.delete(url, params?, config?)
|
|
||||||
* ##### axios.trace(url, config?)
|
|
||||||
* ##### axios.connect(url, config?)
|
|
||||||
|
|
||||||
|
|
||||||
常用例子,其他同理:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// 发送 GET 请求
|
|
||||||
axios.get('/test');
|
|
||||||
|
|
||||||
// 携带参数
|
|
||||||
axios.get('/test', { test: 1 });
|
|
||||||
|
|
||||||
// 携带额外配置
|
|
||||||
axios.get('/test', { test: 1 }, {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json; charset=utf-8'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 发送 POST 请求
|
|
||||||
axios.post('/test');
|
|
||||||
|
|
||||||
// 携带数据
|
|
||||||
axios.post('/test', { test: 1 });
|
|
||||||
|
|
||||||
// 携带额外配置
|
|
||||||
axios.post('/test', { test: 1 }, {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json; charset=utf-8'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## 配置`config`
|
|
||||||
|
|
||||||
非全平台兼容的属性只会在平台支持的情况下生效。
|
|
||||||
|
|
||||||
|参数|类型|默认值|说明|全平台兼容|
|
|
||||||
|:-|:-|:-|:-|:-|
|
|
||||||
|adapter|Function|[查看](https://github.com/early-autumn/axios-miniprogram/blob/master/src/defaults.ts)|自定义适配器|是|
|
|
||||||
|baseURL|String| |基础地址|是|
|
|
||||||
|url|String| |请求地址|是|
|
|
||||||
|method|String|get|请求方法| |
|
|
||||||
|params|Object| |请求参数|是|
|
|
||||||
|data|String/Object/ArrayBuffer| |请求数据|是|
|
|
||||||
|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)|自定义合法状态码|是|
|
|
||||||
|paramsSerializer|Function| |自定义参数序列化|是|
|
|
||||||
|transformRequest|Function/Array<.Function>| |自定义转换请求数据|是|
|
|
||||||
|transformResponse|Function/Array<.Function>| |自定义转换响应数据|是|
|
|
||||||
|errorHandler|Function| |自定义错误处理|是|
|
|
||||||
|cancelToken|Object| |取消令牌|是|
|
|
||||||
|timeout|Number|10000|超时时间| |
|
|
||||||
|dataType|String|json|响应数据格式|是|
|
|
||||||
|responseType|String|text|响应数据类型|是|
|
|
||||||
|enableHttp2|Boolean|false|开启 http2| |
|
|
||||||
|enableQuic|Boolean|false|开启 quic| |
|
|
||||||
|enableCache|Boolean|false|开启 cache| |
|
|
||||||
|sslVerify|Boolean|true|验证 ssl 证书| |
|
|
||||||
|
|
||||||
#### `config.method`的合法值
|
|
||||||
|
|
||||||
可以使用大写,也可以使用小写。
|
|
||||||
|
|
||||||
|值|说明|全平台兼容|
|
|
||||||
|:-|:-|:-|
|
|
||||||
|OPTIONS| | |
|
|
||||||
|GET| |是|
|
|
||||||
|HEAD| | |
|
|
||||||
|POST| |是|
|
|
||||||
|PUT| |是|
|
|
||||||
|DELETE| |是|
|
|
||||||
|TRACE| | |
|
|
||||||
|CONNECT| | |
|
|
||||||
|
|
||||||
#### `config.dataType`的合法值
|
|
||||||
|
|
||||||
|值|说明|全平台兼容|
|
|
||||||
|:-|:-|:-|
|
|
||||||
|json|返回的数据为 JSON,返回后会对返回的数据进行一次 JSON.parse|是|
|
|
||||||
|其他|不对返回的内容进行 JSON.parse|是|
|
|
||||||
|
|
||||||
#### `config.responseType`的合法值
|
|
||||||
|
|
||||||
|值|说明|全平台兼容|
|
|
||||||
|:-|:-|:-|
|
|
||||||
|text|响应的数据为文本|是|
|
|
||||||
|arraybuffer|响应的数据为 ArrayBuffer|是|
|
|
||||||
|
|
||||||
#### 自定义合法状态码`config.validateStatus`
|
|
||||||
|
|
||||||
可以让请求按照您的要求成功或者失败。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
axios('/test', {
|
|
||||||
validateStatus: function validateStatus(status) {
|
|
||||||
// 这样,状态码在 200 到 400 之间都是请求成功
|
|
||||||
return status >= 200 && status < 400;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 自定义参数序列化`config.paramsSerializer`
|
|
||||||
|
|
||||||
可以使用自己的规则去序列化参数。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
axios('/test', {
|
|
||||||
paramsSerializer: function paramsSerializer(params) {
|
|
||||||
return qs.stringify(params, {arrayFormat: 'brackets'});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 自定义转换数据
|
|
||||||
|
|
||||||
可以在请求发出之前转换请求数据,在请求成功之后转换响应数据。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
axios('/test', {
|
|
||||||
transformRequest: [function transformRequest(data, headers) {
|
|
||||||
// 转换请求数据
|
|
||||||
return data;
|
|
||||||
}],
|
|
||||||
transformResponse: [function transformResponse(data) {
|
|
||||||
// 转换响应数据
|
|
||||||
return data;
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 自定义错误处理`config.errorHandler`
|
|
||||||
|
|
||||||
可以添加到默认配置中,统一处理错误。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
axios.defaults.errorHandler = function errorHandler(error) {
|
|
||||||
// 做一些想做的事情
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const instance = axios.create({
|
|
||||||
errorHandler: function errorHandler(error) {
|
|
||||||
// 做一些想做的事情
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
也可以发送请求时通过自定义配置传入。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
axios('/test', {
|
|
||||||
errorHandler: function errorHandler(error) {
|
|
||||||
// 做一些想做的事情
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 自定义平台适配器`config.adapter`
|
|
||||||
|
|
||||||
您可以手动适配当前所处的平台。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
axios.defaults.adapter = function adapter(adapterConfig) {
|
|
||||||
const {
|
|
||||||
// 请求地址
|
|
||||||
url,
|
|
||||||
// 请求方法
|
|
||||||
method,
|
|
||||||
// 请求数据
|
|
||||||
data,
|
|
||||||
// 请求头 同 headers
|
|
||||||
header,
|
|
||||||
// 请求头 同 header
|
|
||||||
headers,
|
|
||||||
// 响应数据格式
|
|
||||||
dataType,
|
|
||||||
// 响应数据类型
|
|
||||||
responseType,
|
|
||||||
// 超时时间
|
|
||||||
timeout,
|
|
||||||
// 开启 http2
|
|
||||||
enableHttp2,
|
|
||||||
// 开启 quic
|
|
||||||
enableQuic,
|
|
||||||
// 开启 cache
|
|
||||||
enableCache,
|
|
||||||
// 验证 ssl 证书
|
|
||||||
sslVerify,
|
|
||||||
// 成功的回调函数
|
|
||||||
success,
|
|
||||||
// 失败的回调函数
|
|
||||||
fail
|
|
||||||
} = adapterConfig;
|
|
||||||
|
|
||||||
// 在 adapterConfig 中选择您需要的参数发送请求
|
|
||||||
return wx.request({
|
|
||||||
url,
|
|
||||||
method,
|
|
||||||
data,
|
|
||||||
header,
|
|
||||||
success,
|
|
||||||
fail
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果 adapterConfig 的数据结构适用于当前平台,则可以。
|
|
||||||
axios.defaults.adapter = wx.request;
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 默认配置`defaults`
|
|
||||||
|
|
||||||
##### 全局默认配置`axios.defaults`
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
axios.defaults.baseURL = 'https://www.xxx.com';
|
|
||||||
axios.defaults.headers.common['Accept'] = 'application/json, test/plain, */*';
|
|
||||||
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
|
|
||||||
```
|
|
||||||
|
|
||||||
##### 自定义实例默认配置
|
|
||||||
|
|
||||||
可以创建时传入。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const instance = axios.create({
|
|
||||||
baseURL: 'https://www.xxx.com',
|
|
||||||
headers: {
|
|
||||||
common: {
|
|
||||||
'Accept': 'application/json, test/plain, */*'
|
|
||||||
},
|
|
||||||
post: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
也可以创建后修改。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
instance.defaults.baseURL = 'https://www.xxx.com';
|
|
||||||
instance.defaults.headers.common['Accept'] = 'application/json, test/plain, */*';
|
|
||||||
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
|
|
||||||
```
|
|
||||||
|
|
||||||
##### 配置优先顺序
|
|
||||||
|
|
||||||
发送请求时,会使用默认配置`defaults`和自定义配置`config`合并出请求配置`requestConfig`,然后用合并出的请求配置`requestConfig`去发送请求,多数情况下,后者优先级要高于前者,具体合并策略可以参考 [mergeConfig.ts](https://github.com/early-autumn/axios-miniprogram/blob/master/src/core/mergeConfig.ts) 的实现。
|
|
||||||
|
|
||||||
## 响应体`response`
|
|
||||||
|
|
||||||
非全平台兼容的属性只会在平台支持的情况下生效。
|
|
||||||
|
|
||||||
|属性|类型|说明|全平台兼容|
|
|
||||||
|:-|:-|:-|:-|
|
|
||||||
|status|Number|状态码|是|
|
|
||||||
|statusText|String|状态文本|是|
|
|
||||||
|data|String/Object/ArrayBuffer|开发者服务器返回的数据|是|
|
|
||||||
|headers|Object|响应头|是|
|
|
||||||
|config|Object|Axios 请求配置|是|
|
|
||||||
|cookies|Array<.String>|开发者服务器返回的 cookies,格式为字符串数组| |
|
|
||||||
|profile|Object|网络请求过程中一些关键时间点的耗时信息| |
|
|
||||||
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
### `axios.interceptors`
|
|
||||||
|
|
||||||
可以先拦截请求或响应,然后再由then或catch处理。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// 添加请求拦截器
|
|
||||||
axios.interceptors.request.use(function (config) {
|
|
||||||
// 在发送请求之前做些什么
|
|
||||||
console.log('request');
|
|
||||||
return config;
|
|
||||||
}, function (error) {
|
|
||||||
//处理请求错误
|
|
||||||
return Promise.reject(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 添加响应拦截器
|
|
||||||
axios.interceptors.response.use(function (response) {
|
|
||||||
// 请求成功后做些什么
|
|
||||||
console.log('response');
|
|
||||||
return response;
|
|
||||||
}, function (error) {
|
|
||||||
// 处理响应错误
|
|
||||||
return Promise.reject(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
axios('/test').then(function (response){
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
||||||
|
|
||||||
// log 'request' 'response' 'ok'
|
|
||||||
```
|
|
||||||
|
|
||||||
如果以后需要删除拦截器,则可以。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
|
|
||||||
axios.interceptors.request.eject(myInterceptor);
|
|
||||||
```
|
|
||||||
|
|
||||||
还可以将拦截器添加到`axios`的`自定义实例`中。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
|
|
||||||
axios.interceptors.request.eject(myInterceptor);
|
|
||||||
```
|
|
||||||
|
|
||||||
### `axios.CancelToken`
|
|
||||||
|
|
||||||
可以使用`CancelToken`取消已经发出的请求。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
let cancel;
|
|
||||||
|
|
||||||
axios('/test', {
|
|
||||||
cancelToken: new axios.CancelToken(function (c){
|
|
||||||
cancel = c;
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
cancel('取消请求');
|
|
||||||
```
|
|
||||||
|
|
||||||
还可以使用`CancelToken.source`工厂方法创建`CancelToken`。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const source = axios.CancelToken.source();
|
|
||||||
|
|
||||||
axios('/test', {
|
|
||||||
cancelToken: source.token
|
|
||||||
});
|
|
||||||
|
|
||||||
source.cancel('取消请求');
|
|
||||||
```
|
|
||||||
|
|
||||||
### `axios.isCancel`
|
|
||||||
|
|
||||||
可以判断当前错误是否来自取消请求
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
axios('/test').catch((error) => {
|
|
||||||
if(axios.isCancel(error)){
|
|
||||||
// 请求被取消了
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### `axios.getUri(config)`
|
|
||||||
|
|
||||||
根据配置中的`url`和`params`生成一个`URI`。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// uri === '/test?id=1'
|
|
||||||
const uri = axios.getUri({
|
|
||||||
url: '/test',
|
|
||||||
params: { id: 1 }
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### `axios.create(defaults)`
|
|
||||||
|
|
||||||
创建一个`自定义实例`,传入的自定义默认配置`defaults`会和`axios`的默认配置`axios.defaults`合并成`自定义实例`的默认配置。
|
|
||||||
|
|
||||||
`自定义实例`拥有和`axios`相同的调用方式和请求方法的别名。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
axios.defaults.baseURL = 'https://www.xxx.com';
|
|
||||||
|
|
||||||
const instance = axios.create({
|
|
||||||
params: {
|
|
||||||
id: 1
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 最终请求的 URL 是这样的 => https://www.xxx.com/test?id=1
|
|
||||||
// https://www.xxx.com 来自 axios.defaults.baseURL
|
|
||||||
// /test 来自传入的 '/test'
|
|
||||||
// id=1 来自 instance.defaults.params
|
|
||||||
instance('/test');
|
|
||||||
instance.get('/test');
|
|
||||||
```
|
|
||||||
|
|
||||||
### `axios.Axios`
|
|
||||||
|
|
||||||
`axios.Axios`是一个类,其实`axios`就是`axios.Axios`类的实例改造而来的,`axios.create(defaults)`创建的也是`axios.Axios`的实例。
|
|
||||||
|
|
||||||
直接实例化`axios.Axios`可以得到一个`原始实例`,不能当函数调用,传入的自定义配置就是`原始实例`的默认配置,而不会像`axios.create(defaults)`一样去合并`axios`中的默认配置。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
axios.defaults.baseURL = 'https://www.xxx.com';
|
|
||||||
|
|
||||||
const instance = new axios.Axios({
|
|
||||||
params: { value: 123 }
|
|
||||||
});
|
|
||||||
|
|
||||||
// 最终请求的 URL 是这样的 => /test?value=123
|
|
||||||
// /test 来自传入的 '/test'
|
|
||||||
// value=123 来自 instance.defaults.params
|
|
||||||
instance.get('/test');
|
|
||||||
```
|
|
||||||
|
|
||||||
## 执行流程
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
axios('/test').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 => config.errorHandler => axios.interceptors.response => catch
|
|
||||||
```
|
|
21
SECURITY.md
21
SECURITY.md
|
@ -1,21 +0,0 @@
|
||||||
# Security Policy
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
Use this section to tell people about which versions of your project are
|
|
||||||
currently being supported with security updates.
|
|
||||||
|
|
||||||
| Version | Supported |
|
|
||||||
| ------- | ------------------ |
|
|
||||||
| 5.1.x | :white_check_mark: |
|
|
||||||
| 5.0.x | :x: |
|
|
||||||
| 4.0.x | :white_check_mark: |
|
|
||||||
| < 4.0 | :x: |
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
Use this section to tell people how to report a vulnerability.
|
|
||||||
|
|
||||||
Tell them where to go, how often they can expect to get an update on a
|
|
||||||
reported vulnerability, what to expect if the vulnerability is accepted or
|
|
||||||
declined, etc.
|
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"@babel/preset-env",
|
|
||||||
{
|
|
||||||
"targets": {
|
|
||||||
"node": "current"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"@babel/plugin-proposal-optional-chaining",
|
|
||||||
"@babel/plugin-transform-modules-commonjs"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
import adaptive from '../src/adaptive';
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
namespace NodeJS {
|
|
||||||
interface Global {
|
|
||||||
wx: any;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('测试 src/adaptive.ts', () => {
|
|
||||||
it('适配成功', () => {
|
|
||||||
const request = jest.fn();
|
|
||||||
global.wx = {
|
|
||||||
request,
|
|
||||||
};
|
|
||||||
|
|
||||||
const adapter = adaptive();
|
|
||||||
|
|
||||||
expect(adapter).toBe(request);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('适配失败', () => {
|
|
||||||
global.wx = void 0;
|
|
||||||
|
|
||||||
expect(adaptive()).toBeUndefined();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,90 +0,0 @@
|
||||||
import axios from '../src/axios';
|
|
||||||
|
|
||||||
describe('测试 src/axios.ts', () => {
|
|
||||||
it('default', () => {
|
|
||||||
axios('/test').then(void 0, (error) => {
|
|
||||||
expect(error.isAxiosError).toBe(true);
|
|
||||||
expect(error.message).toBe('平台适配失败,您需要参阅文档使用自定义适配器手动适配当前平台');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('axios call', async () => {
|
|
||||||
axios.defaults.adapter = (config): any => {
|
|
||||||
config.success({ status: 200, data: {}, headers: {} });
|
|
||||||
|
|
||||||
expect(config.method).toBe(config.url.toUpperCase().replace('/', ''));
|
|
||||||
|
|
||||||
return 'task';
|
|
||||||
};
|
|
||||||
|
|
||||||
await axios({ url: '/get' });
|
|
||||||
await axios('/get');
|
|
||||||
await axios.request({ url: '/get' });
|
|
||||||
await axios.options('options');
|
|
||||||
await axios.get('get');
|
|
||||||
await axios.head('head');
|
|
||||||
await axios.post('post');
|
|
||||||
await axios.put('put');
|
|
||||||
await axios.delete('delete');
|
|
||||||
await axios.trace('trace');
|
|
||||||
await axios.connect('connect');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('axios 携带参数', async () => {
|
|
||||||
const url = '/test';
|
|
||||||
const params = {
|
|
||||||
id: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
axios.defaults.adapter = (config): any => {
|
|
||||||
config.success({ status: 200, data: {}, headers: {} });
|
|
||||||
|
|
||||||
expect(config.method).toBe('GET');
|
|
||||||
expect(config.url).toBe('/test?id=1');
|
|
||||||
|
|
||||||
return 'task';
|
|
||||||
};
|
|
||||||
|
|
||||||
await axios({
|
|
||||||
url,
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
await axios(url, {
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
await axios.get(url, params);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('axios 携带数据', async () => {
|
|
||||||
const url = '/test';
|
|
||||||
const data = {
|
|
||||||
id: 1,
|
|
||||||
};
|
|
||||||
axios.defaults.adapter = (config): any => {
|
|
||||||
config.success({ status: 200, data: '', headers: {} });
|
|
||||||
|
|
||||||
expect(config.method).toBe('POST');
|
|
||||||
expect(config.url).toBe(url);
|
|
||||||
expect(config.data).toEqual(data);
|
|
||||||
|
|
||||||
return 'task';
|
|
||||||
};
|
|
||||||
|
|
||||||
await axios({
|
|
||||||
method: 'post',
|
|
||||||
url,
|
|
||||||
data,
|
|
||||||
});
|
|
||||||
await axios(url, {
|
|
||||||
method: 'post',
|
|
||||||
data,
|
|
||||||
});
|
|
||||||
await axios.post(url, data);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('axios.create 工厂方法', () => {
|
|
||||||
const instance = axios.create();
|
|
||||||
|
|
||||||
expect(instance.defaults).toEqual(axios.defaults);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,15 +0,0 @@
|
||||||
import Cancel from '../../src/cancel/Cancel';
|
|
||||||
|
|
||||||
describe('测试 src/cancel/Cancel.ts', () => {
|
|
||||||
it('默认', () => {
|
|
||||||
const cancel = new Cancel();
|
|
||||||
|
|
||||||
expect(cancel.toString()).toBe('Cancel');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('自定义', () => {
|
|
||||||
const cancel = new Cancel('custom');
|
|
||||||
|
|
||||||
expect(cancel.toString()).toBe('Cancel: custom');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,27 +0,0 @@
|
||||||
import CancelToken from '../../src/cancel/CancelToken';
|
|
||||||
|
|
||||||
describe('测试 src/cancel/CancelToken.ts', () => {
|
|
||||||
it('实例化', () => {
|
|
||||||
const token = new CancelToken(function (cancel) {
|
|
||||||
cancel('取消');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 应该抛出取消
|
|
||||||
expect(() => token.throwIfRequested()).toThrow();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('工厂方法', () => {
|
|
||||||
const source = CancelToken.source();
|
|
||||||
|
|
||||||
// 还没有取消 返回 Undefuned
|
|
||||||
expect(source.token.throwIfRequested()).toBeUndefined();
|
|
||||||
|
|
||||||
source.cancel('取消');
|
|
||||||
|
|
||||||
// 应该抛出取消
|
|
||||||
expect(() => source.token.throwIfRequested()).toThrow();
|
|
||||||
|
|
||||||
// 重复取消无效
|
|
||||||
source.cancel('取消');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,12 +0,0 @@
|
||||||
import isCancel from '../../src/cancel/isCancel';
|
|
||||||
import Cancel from '../../src/cancel/Cancel';
|
|
||||||
|
|
||||||
describe('测试 src/cancel/isCancel', () => {
|
|
||||||
it('是一个取消?', () => {
|
|
||||||
const cancel1 = {};
|
|
||||||
const cancel2 = new Cancel();
|
|
||||||
|
|
||||||
expect(isCancel(cancel1)).toBe(false);
|
|
||||||
expect(isCancel(cancel2)).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,63 +0,0 @@
|
||||||
import Axios from '../../src/core/Axios';
|
|
||||||
|
|
||||||
const instance = new Axios();
|
|
||||||
|
|
||||||
describe('测试 src/core/Axios.ts', () => {
|
|
||||||
it('defaults', () => {
|
|
||||||
expect(instance.defaults).toEqual({});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getUri', () => {
|
|
||||||
expect(instance.getUri({})).toEqual('');
|
|
||||||
expect(instance.getUri({ url: '/test' })).toEqual('/test');
|
|
||||||
expect(instance.getUri({ url: '', params: { id: 1 } })).toEqual('id=1');
|
|
||||||
expect(instance.getUri({ url: '/test', params: { id: 1 } })).toEqual('/test?id=1');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('interceptors 成功', () => {
|
|
||||||
instance.defaults.adapter = function adapter({ data, success }): any {
|
|
||||||
expect(data).toBe('interceptors_request');
|
|
||||||
|
|
||||||
success({ data: 'data', headers: {} });
|
|
||||||
|
|
||||||
return 'task';
|
|
||||||
};
|
|
||||||
|
|
||||||
instance.interceptors.request.use(function (config) {
|
|
||||||
config.data = 'interceptors_request';
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
|
|
||||||
instance.interceptors.response.use(function (response) {
|
|
||||||
response.data = 'interceptors_response';
|
|
||||||
return response;
|
|
||||||
});
|
|
||||||
|
|
||||||
instance
|
|
||||||
.request({
|
|
||||||
method: 'post',
|
|
||||||
data: '',
|
|
||||||
})
|
|
||||||
.then(({ data }) => expect(data).toBe('interceptors_response'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('interceptors 失败', () => {
|
|
||||||
instance.interceptors.response.use((response) => Promise.reject(response));
|
|
||||||
|
|
||||||
instance
|
|
||||||
.request({
|
|
||||||
method: 'post',
|
|
||||||
data: '',
|
|
||||||
})
|
|
||||||
.then(void 0, (error) => expect(error.data).toBe('interceptors_response'));
|
|
||||||
|
|
||||||
instance.interceptors.request.use((config) => Promise.reject(config));
|
|
||||||
|
|
||||||
instance
|
|
||||||
.request({
|
|
||||||
method: 'post',
|
|
||||||
data: '',
|
|
||||||
})
|
|
||||||
.then(void 0, (error) => expect(error.method).toBe('post'));
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,61 +0,0 @@
|
||||||
import InterceptorManager from '../../src/core/InterceptorManager';
|
|
||||||
|
|
||||||
describe('测试 src/core/InterceptorManager.ts', () => {
|
|
||||||
it('实例化', () => {
|
|
||||||
const interceptor = new InterceptorManager();
|
|
||||||
const executor = jest.fn();
|
|
||||||
|
|
||||||
interceptor.forEach(executor);
|
|
||||||
|
|
||||||
// executor 不应该被执行
|
|
||||||
expect(executor.mock.calls.length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('注册和取消注册', () => {
|
|
||||||
const interceptor = new InterceptorManager();
|
|
||||||
const executor1 = jest.fn();
|
|
||||||
const executor2 = jest.fn();
|
|
||||||
const id1 = interceptor.use(() => void 0);
|
|
||||||
const id2 = interceptor.use(() => void 0);
|
|
||||||
interceptor.forEach(executor1);
|
|
||||||
|
|
||||||
// executor1 应该被执行了两次
|
|
||||||
expect(executor1.mock.calls.length).toBe(2);
|
|
||||||
|
|
||||||
interceptor.eject(id1);
|
|
||||||
interceptor.eject(id2);
|
|
||||||
interceptor.forEach(executor2);
|
|
||||||
|
|
||||||
// executor2 不应该被执行
|
|
||||||
expect(executor2.mock.calls.length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('倒序遍历', () => {
|
|
||||||
const interceptor = new InterceptorManager();
|
|
||||||
let id = 0;
|
|
||||||
|
|
||||||
// 应该后被执行
|
|
||||||
interceptor.use((id) => expect(id).toBe(1));
|
|
||||||
|
|
||||||
// 应该先被执行
|
|
||||||
interceptor.use((id) => expect(id).toBe(0));
|
|
||||||
|
|
||||||
interceptor.forEach(({ resolved }) => {
|
|
||||||
resolved(id++);
|
|
||||||
}, 'reverse');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('异常', () => {
|
|
||||||
const interceptor = new InterceptorManager();
|
|
||||||
|
|
||||||
interceptor.use(
|
|
||||||
() => void 0,
|
|
||||||
(error: any) => {
|
|
||||||
expect(error).toBe('error');
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
interceptor.forEach(({ rejected }) => rejected?.('error'));
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,55 +0,0 @@
|
||||||
import { CancelAction } from '../../src/types';
|
|
||||||
import dispatchRequest from '../../src/core/dispatchRequest';
|
|
||||||
import CancelToken from '../../src/cancel/CancelToken';
|
|
||||||
import isCancel from '../../src/cancel/isCancel';
|
|
||||||
|
|
||||||
describe('测试 src/core/dispatchRequest.ts', () => {
|
|
||||||
it('默认', () => {
|
|
||||||
dispatchRequest({}).then(void 0, (err) => {
|
|
||||||
expect(err.message).toBe('平台适配失败,您需要参阅文档使用自定义适配器手动适配当前平台');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('请求失败', () => {
|
|
||||||
dispatchRequest({
|
|
||||||
adapter({ success }): any {
|
|
||||||
success({ status: 200, data: '' });
|
|
||||||
|
|
||||||
return 'task';
|
|
||||||
},
|
|
||||||
validateStatus(status) {
|
|
||||||
return status === -1;
|
|
||||||
},
|
|
||||||
}).then(void 0, (err) => expect(err.response.status).toBe(200));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('自定义错误处理', () => {
|
|
||||||
dispatchRequest({
|
|
||||||
adapter({ fail }): any {
|
|
||||||
fail({});
|
|
||||||
|
|
||||||
return 'task';
|
|
||||||
},
|
|
||||||
errorHandler(error) {
|
|
||||||
error.errorHandler = true;
|
|
||||||
return error;
|
|
||||||
},
|
|
||||||
}).then(void 0, (error) => expect(error.errorHandler).toBe(true));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('取消请求', () => {
|
|
||||||
let cancel: CancelAction;
|
|
||||||
|
|
||||||
dispatchRequest({
|
|
||||||
adapter({ success }) {
|
|
||||||
cancel();
|
|
||||||
setTimeout(() => {
|
|
||||||
success({ status: 200, data: '' });
|
|
||||||
});
|
|
||||||
},
|
|
||||||
cancelToken: new CancelToken(function executor(c) {
|
|
||||||
cancel = c;
|
|
||||||
}),
|
|
||||||
}).then(void 0, (err) => expect(isCancel(err)).toBe(true));
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,35 +0,0 @@
|
||||||
import flattenHeaders from '../../src/core/flattenHeaders';
|
|
||||||
|
|
||||||
describe('测试 src/core/flattenHeaders.ts', () => {
|
|
||||||
it('默认', () => {
|
|
||||||
expect(flattenHeaders({})).toEqual({});
|
|
||||||
expect(flattenHeaders({ headers: {} })).toEqual({});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('默认 get', () => {
|
|
||||||
expect(
|
|
||||||
flattenHeaders({
|
|
||||||
headers: {
|
|
||||||
common: { common: 'common' },
|
|
||||||
get: { get: 'get' },
|
|
||||||
post: { post: 'post' },
|
|
||||||
rest: 'rest',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
).toEqual({ common: 'common', get: 'get', rest: 'rest' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('拉平', () => {
|
|
||||||
expect(
|
|
||||||
flattenHeaders({
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
common: { common: 'common' },
|
|
||||||
get: { get: 'get' },
|
|
||||||
post: { post: 'post' },
|
|
||||||
rest: 'rest',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
).toEqual({ common: 'common', post: 'post', rest: 'rest' });
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,57 +0,0 @@
|
||||||
import { AxiosRequestConfig } from '../../src/types';
|
|
||||||
import mergeConfig from '../../src/core/mergeConfig';
|
|
||||||
import defaults from '../../src/defaults';
|
|
||||||
|
|
||||||
describe('测试 src/core/mergeConfig.ts', () => {
|
|
||||||
it('默认', () => {
|
|
||||||
expect(mergeConfig()).toEqual({});
|
|
||||||
|
|
||||||
expect(mergeConfig({ baseURL: 'https://www.xxx.com' })).toEqual({ baseURL: 'https://www.xxx.com' });
|
|
||||||
|
|
||||||
expect(mergeConfig(void 0, { baseURL: 'https://www.xxx.com' })).toEqual({ baseURL: 'https://www.xxx.com' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('只取 config2', () => {
|
|
||||||
const config2 = { url: 'https://www.config2.com', data: { config2: 0 } };
|
|
||||||
const config = mergeConfig(defaults, config2);
|
|
||||||
|
|
||||||
expect(config.url).toEqual(config2.url);
|
|
||||||
expect(config.data).toEqual(config2.data);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('优先取 config2', () => {
|
|
||||||
expect(mergeConfig(defaults, {})).toEqual(defaults);
|
|
||||||
|
|
||||||
const config2: AxiosRequestConfig = {
|
|
||||||
baseURL: 'https://www.config2.com',
|
|
||||||
method: 'post',
|
|
||||||
timeout: 10000,
|
|
||||||
};
|
|
||||||
|
|
||||||
const config = mergeConfig(defaults, config2);
|
|
||||||
|
|
||||||
expect(config.baseURL).toEqual(config2.baseURL);
|
|
||||||
expect(config.method).toEqual(config2.method);
|
|
||||||
expect(config.timeout).toEqual(config2.timeout);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('深度合并', () => {
|
|
||||||
const config1 = { params: { config1: 0 }, headers: { Config1: '0' } };
|
|
||||||
const config2 = { params: { config2: 0 }, headers: { Config2: '0' } };
|
|
||||||
|
|
||||||
expect(mergeConfig(config1, {})).toEqual(config1);
|
|
||||||
|
|
||||||
expect(mergeConfig(config1, config2)).toEqual({
|
|
||||||
params: { config1: 0, config2: 0 },
|
|
||||||
headers: { Config1: '0', Config2: '0' },
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(mergeConfig({ params: {} }, { params: { config: 'config2' } })).toEqual({
|
|
||||||
params: { config: 'config2' },
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(mergeConfig({ params: { config: 'config1' } }, {})).toEqual({
|
|
||||||
params: { config: 'config1' },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,36 +0,0 @@
|
||||||
import request from '../../src/core/request';
|
|
||||||
import CancelToken from '../../src/cancel/CancelToken';
|
|
||||||
import isCancel from '../../src/cancel/isCancel';
|
|
||||||
|
|
||||||
describe('测试 src/core/request.ts', () => {
|
|
||||||
it('默认', () => {
|
|
||||||
request({}).then(void 0, (err) =>
|
|
||||||
expect(err.message).toBe('平台适配失败,您需要参阅文档使用自定义适配器手动适配当前平台')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('请求失败', () => {
|
|
||||||
request({
|
|
||||||
adapter({ fail }): any {
|
|
||||||
fail({});
|
|
||||||
|
|
||||||
return 'task';
|
|
||||||
},
|
|
||||||
}).then(void 0, (err) => expect(err.message).toBe('配置不正确或者网络异常'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('取消请求', () => {
|
|
||||||
request({
|
|
||||||
adapter({ fail }) {
|
|
||||||
setTimeout(fail);
|
|
||||||
|
|
||||||
return {
|
|
||||||
abort: jest.fn(),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
cancelToken: new CancelToken(function executor(c) {
|
|
||||||
c();
|
|
||||||
}),
|
|
||||||
}).then(void 0, (err) => expect(isCancel(err)).toBe(true));
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,27 +0,0 @@
|
||||||
import { Data } from '../../src/types';
|
|
||||||
import transformData from '../../src/core/transformData';
|
|
||||||
|
|
||||||
describe('测试 src/core/transformData.ts', () => {
|
|
||||||
it('默认', () => {
|
|
||||||
expect(transformData({ a: 1 }, {})).toEqual({ a: 1 });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('转换', () => {
|
|
||||||
function transform(data: Data) {
|
|
||||||
return data + '1';
|
|
||||||
}
|
|
||||||
expect(transformData('1', {}, transform)).toEqual('11');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('多次转换', () => {
|
|
||||||
const transforms = [
|
|
||||||
function transform(data: Data) {
|
|
||||||
return data + '1';
|
|
||||||
},
|
|
||||||
function transform(data: Data) {
|
|
||||||
return data + '1';
|
|
||||||
},
|
|
||||||
];
|
|
||||||
expect(transformData('1', {}, transforms)).toEqual('111');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { methodToLowercase, methodToUppercase } from '../../src/core/transformMethod';
|
|
||||||
|
|
||||||
describe('测试 src/core/transformMethod.ts', () => {
|
|
||||||
it('默认', () => {
|
|
||||||
expect(methodToLowercase()).toBe('get');
|
|
||||||
expect(methodToUppercase()).toBe('GET');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('传参', () => {
|
|
||||||
expect(methodToLowercase('POST')).toBe('post');
|
|
||||||
expect(methodToUppercase('post')).toBe('POST');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,42 +0,0 @@
|
||||||
import transformRequest from '../../src/core/transformRequest';
|
|
||||||
|
|
||||||
describe('测试 src/core/transformRequest.ts', () => {
|
|
||||||
it('默认', () => {
|
|
||||||
expect(transformRequest({})).toEqual({
|
|
||||||
url: '/',
|
|
||||||
method: 'GET',
|
|
||||||
headers: void 0,
|
|
||||||
data: void 0,
|
|
||||||
dataType: void 0,
|
|
||||||
enableCache: void 0,
|
|
||||||
enableHttp2: void 0,
|
|
||||||
enableQuic: void 0,
|
|
||||||
header: void 0,
|
|
||||||
responseType: void 0,
|
|
||||||
sslVerify: void 0,
|
|
||||||
timeout: void 0,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('基本', () => {
|
|
||||||
const request = transformRequest({
|
|
||||||
baseURL: 'https://www.xxx.com///',
|
|
||||||
method: 'get',
|
|
||||||
url: '/test',
|
|
||||||
params: {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const request2 = transformRequest({
|
|
||||||
baseURL: 'https://www.xxx.com',
|
|
||||||
method: 'get',
|
|
||||||
url: 'https://www.yyy.com/test',
|
|
||||||
params: {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(request.url).toEqual('https://www.xxx.com/test?id=1');
|
|
||||||
expect(request2.url).toEqual('https://www.yyy.com/test?id=1');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,38 +0,0 @@
|
||||||
import transformResponse from '../../src/core/transformResponse';
|
|
||||||
|
|
||||||
describe('测试 src/core/transformResponse.ts', () => {
|
|
||||||
it('默认', () => {
|
|
||||||
expect(transformResponse({ data: {} }, {})).toEqual({
|
|
||||||
status: 400,
|
|
||||||
statusText: 'Bad Adapter',
|
|
||||||
data: {},
|
|
||||||
headers: {},
|
|
||||||
config: {},
|
|
||||||
cookies: void 0,
|
|
||||||
profile: void 0,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('status + headers', () => {
|
|
||||||
expect(transformResponse({ status: 200, headers: { status: 'ok' }, data: {} }, {})).toEqual({
|
|
||||||
status: 200,
|
|
||||||
statusText: 'OK',
|
|
||||||
data: {},
|
|
||||||
headers: { status: 'ok' },
|
|
||||||
config: {},
|
|
||||||
cookies: void 0,
|
|
||||||
profile: void 0,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('statusCode + header', () => {
|
|
||||||
expect(transformResponse({ statusCode: 204, header: { status: 'ok' }, data: {} }, {})).toEqual({
|
|
||||||
status: 204,
|
|
||||||
statusText: '',
|
|
||||||
data: {},
|
|
||||||
headers: { status: 'ok' },
|
|
||||||
config: {},
|
|
||||||
cookies: void 0,
|
|
||||||
profile: void 0,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,82 +0,0 @@
|
||||||
import buildURL from '../../src/helpers/buildURL';
|
|
||||||
|
|
||||||
describe('测试 src/helpers/buildURL.ts', () => {
|
|
||||||
it('url', () => {
|
|
||||||
expect(buildURL('/test')).toBe('/test');
|
|
||||||
expect(buildURL('/test?id=1')).toBe('/test?id=1');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('url + params', () => {
|
|
||||||
expect(
|
|
||||||
buildURL('/test', {
|
|
||||||
test: 1,
|
|
||||||
})
|
|
||||||
).toBe('/test?test=1');
|
|
||||||
expect(
|
|
||||||
buildURL('/test?id=1', {
|
|
||||||
test: 1,
|
|
||||||
})
|
|
||||||
).toBe('/test?id=1&test=1');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('url + params + paramsSerializer', () => {
|
|
||||||
expect(
|
|
||||||
buildURL(
|
|
||||||
'/test',
|
|
||||||
{
|
|
||||||
test: 1,
|
|
||||||
},
|
|
||||||
() => 'paramsSerializer=ok'
|
|
||||||
)
|
|
||||||
).toBe('/test?paramsSerializer=ok');
|
|
||||||
expect(
|
|
||||||
buildURL(
|
|
||||||
'/test?id=1',
|
|
||||||
{
|
|
||||||
test: 1,
|
|
||||||
},
|
|
||||||
() => 'paramsSerializer=ok'
|
|
||||||
)
|
|
||||||
).toBe('/test?id=1¶msSerializer=ok');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('params 是数组', () => {
|
|
||||||
expect(
|
|
||||||
buildURL('/test', {
|
|
||||||
ids: [1],
|
|
||||||
})
|
|
||||||
).toBe('/test?ids[]=1');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('params 是时间对象', () => {
|
|
||||||
const date = new Date();
|
|
||||||
expect(
|
|
||||||
buildURL('/test', {
|
|
||||||
date,
|
|
||||||
})
|
|
||||||
).toBe(`/test?date=${date.toISOString()}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('params 是普通对象', () => {
|
|
||||||
const obj = {};
|
|
||||||
expect(
|
|
||||||
buildURL('/test', {
|
|
||||||
obj,
|
|
||||||
})
|
|
||||||
).toBe(`/test?obj=%7B%7D`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('删除哈希', () => {
|
|
||||||
expect(buildURL('/test#192929')).toBe('/test');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('容错', () => {
|
|
||||||
expect(
|
|
||||||
buildURL('/test', {
|
|
||||||
null: null,
|
|
||||||
undefined: void 0,
|
|
||||||
NaN: NaN,
|
|
||||||
})
|
|
||||||
).toBe('/test');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,8 +0,0 @@
|
||||||
import combineURL from '../../src/helpers/combineURL';
|
|
||||||
|
|
||||||
describe('测试 src/helpers/combineURL.ts', () => {
|
|
||||||
it('run', () => {
|
|
||||||
expect(combineURL('1/2', '3/4')).toBe('1/2/3/4');
|
|
||||||
expect(combineURL('1/2///', '////3/4')).toBe('1/2/3/4');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,10 +0,0 @@
|
||||||
import isAbsoluteURL from '../../src/helpers/isAbsoluteURL';
|
|
||||||
|
|
||||||
describe('测试 src/helpers/isAbsoluteURL.ts', () => {
|
|
||||||
it('run', () => {
|
|
||||||
expect(isAbsoluteURL('1/2')).toBe(false);
|
|
||||||
expect(isAbsoluteURL('/1/2')).toBe(false);
|
|
||||||
expect(isAbsoluteURL('///1/2')).toBe(true);
|
|
||||||
expect(isAbsoluteURL('http://1/2')).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,41 +0,0 @@
|
||||||
import { encode, isDate, isPlainObject, deepMerge, pick, omit } from '../../src/helpers/utils';
|
|
||||||
|
|
||||||
describe('测试 src/helpers/utils.ts', () => {
|
|
||||||
it('encode 特殊字符转换', () => {
|
|
||||||
expect(encode('@:, []$')).toBe('@:,+[]$');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('isDate', () => {
|
|
||||||
expect(isDate(new Date())).toBe(true);
|
|
||||||
expect(isDate('')).toBe(false);
|
|
||||||
expect(isDate(Date)).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('isPlainObject', () => {
|
|
||||||
expect(isPlainObject({})).toBe(true);
|
|
||||||
expect(isPlainObject(Object.create(null))).toBe(true);
|
|
||||||
expect(isPlainObject('')).toBe(false);
|
|
||||||
expect(isPlainObject(Object)).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('deepMerge', () => {
|
|
||||||
expect(deepMerge({}, {})).toEqual({});
|
|
||||||
expect(deepMerge({ a: 0, b: '1', c: { a: 0, b: '1' } }, { a: 1, b: '1', c: { a: 1, b: '1' } })).toEqual({
|
|
||||||
a: 1,
|
|
||||||
b: '1',
|
|
||||||
c: { a: 1, b: '1' },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('pick', () => {
|
|
||||||
expect(pick({})).toEqual({});
|
|
||||||
|
|
||||||
expect(pick({ a: 0, b: 0 }, 'a')).toEqual({ a: 0 });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('omit', () => {
|
|
||||||
expect(omit({})).toEqual({});
|
|
||||||
|
|
||||||
expect(omit({ a: 0, b: 0 }, 'a')).toEqual({ b: 0 });
|
|
||||||
});
|
|
||||||
});
|
|
74
package.json
74
package.json
|
@ -1,74 +0,0 @@
|
||||||
{
|
|
||||||
"name": "axios-miniprogram",
|
|
||||||
"version": "1.1.3",
|
|
||||||
"description": "基于 Promise 的 HTTP 请求库,适用于各大小程序平台。",
|
|
||||||
"main": "package/index.js",
|
|
||||||
"miniprogram": "package",
|
|
||||||
"types": "types/index.d.ts",
|
|
||||||
"files": [
|
|
||||||
"package",
|
|
||||||
"types"
|
|
||||||
],
|
|
||||||
"scripts": {
|
|
||||||
"build": "rollup -c",
|
|
||||||
"lint": "eslint --ext ts --fix src __tests__",
|
|
||||||
"prettier": "prettier --write --config .prettierrc \"{src,__tests__}/**/*.{js,ts}\"",
|
|
||||||
"test": "jest",
|
|
||||||
"test:watch": "yarn test -- --watch",
|
|
||||||
"test:cov": "yarn test -- --coverage",
|
|
||||||
"coverage": "yarn test:cov --coverageReporters=text-lcov | coveralls"
|
|
||||||
},
|
|
||||||
"husky": {
|
|
||||||
"hooks": {
|
|
||||||
"pre-commit": "yarn prettier && yarn lint && yarn test:cov && git add ."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jest": {
|
|
||||||
"preset": "ts-jest",
|
|
||||||
"globals": {
|
|
||||||
"ts-jest": {
|
|
||||||
"babelConfig": "test/.babelrc"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/zjx0905/axios-miniprogram.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"axios",
|
|
||||||
"miniprogram",
|
|
||||||
"request",
|
|
||||||
"promise"
|
|
||||||
],
|
|
||||||
"author": "zjx0905",
|
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/zjx0905/axios-miniprogram/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/zjx0905/axios-miniprogram#readme",
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/core": "^7.10.5",
|
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.10.4",
|
|
||||||
"@babel/plugin-transform-modules-commonjs": "^7.10.4",
|
|
||||||
"@babel/plugin-transform-runtime": "^7.10.5",
|
|
||||||
"@babel/preset-env": "^7.10.4",
|
|
||||||
"@babel/preset-typescript": "^7.10.4",
|
|
||||||
"@babel/runtime": "^7.10.5",
|
|
||||||
"@types/jest": "^26.0.5",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^3.7.0",
|
|
||||||
"@typescript-eslint/parser": "^3.7.0",
|
|
||||||
"coveralls": "^3.1.0",
|
|
||||||
"eslint": "^7.5.0",
|
|
||||||
"eslint-config-prettier": "^6.11.0",
|
|
||||||
"eslint-plugin-prettier": "^3.1.4",
|
|
||||||
"husky": "^4.2.5",
|
|
||||||
"jest": "^26.1.0",
|
|
||||||
"prettier": "^2.0.5",
|
|
||||||
"rollup-plugin-babel": "^4.4.0",
|
|
||||||
"rollup-plugin-node-resolve": "^5.2.0",
|
|
||||||
"rollup-plugin-typescript2": "^0.27.1",
|
|
||||||
"ts-jest": "^26.1.3",
|
|
||||||
"typescript": "^3.9.7"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* @Author: early-autumn
|
|
||||||
* @Date: 2020-03-06 20:40:30
|
|
||||||
* @LastEditors: early-autumn
|
|
||||||
* @LastEditTime: 2020-04-28 13:18:34
|
|
||||||
*/
|
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import nodeResolve from 'rollup-plugin-node-resolve';
|
|
||||||
import babel from 'rollup-plugin-babel';
|
|
||||||
import typescript2 from 'rollup-plugin-typescript2';
|
|
||||||
|
|
||||||
function removeDir(name) {
|
|
||||||
try {
|
|
||||||
if (fs.statSync(name).isFile()) {
|
|
||||||
fs.unlinkSync(name);
|
|
||||||
} else {
|
|
||||||
fs.readdirSync(name).forEach((dir) => removeDir(path.join(name, dir)));
|
|
||||||
fs.rmdirSync(name)
|
|
||||||
}
|
|
||||||
} catch (err) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function() {
|
|
||||||
removeDir('package');
|
|
||||||
removeDir('types');
|
|
||||||
|
|
||||||
return {
|
|
||||||
input: 'src/index.ts',
|
|
||||||
output: {
|
|
||||||
file: 'package/index.js',
|
|
||||||
format: 'cjs',
|
|
||||||
indent: false,
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
nodeResolve({ extensions: ['.ts'] }),
|
|
||||||
typescript2({ useTsconfigDeclarationDir: true }),
|
|
||||||
babel({ extensions: ['.ts'] }),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
import { Adapter, Platform } from './types';
|
|
||||||
|
|
||||||
// uniapp
|
|
||||||
declare let uni: Platform;
|
|
||||||
// 微信小程序
|
|
||||||
declare let wx: Platform;
|
|
||||||
// 支付宝小程序
|
|
||||||
declare let my: Platform;
|
|
||||||
// 百度小程序
|
|
||||||
declare let swan: Platform;
|
|
||||||
// 字节跳动小程序
|
|
||||||
declare let tt: Platform;
|
|
||||||
// QQ 小程序
|
|
||||||
declare let qq: Platform;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自适应当前平台
|
|
||||||
*/
|
|
||||||
export default function adaptive(): Adapter | undefined {
|
|
||||||
const stack: (() => Adapter)[] = [
|
|
||||||
() => uni.request,
|
|
||||||
() => wx.request,
|
|
||||||
() => my.request,
|
|
||||||
() => swan.request,
|
|
||||||
() => tt.request,
|
|
||||||
() => qq.request,
|
|
||||||
];
|
|
||||||
|
|
||||||
let adapter: Adapter | undefined;
|
|
||||||
|
|
||||||
while (stack.length !== 0 && adapter === void 0) {
|
|
||||||
try {
|
|
||||||
adapter = (stack.shift() as () => Adapter)();
|
|
||||||
} catch (err) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
return adapter;
|
|
||||||
}
|
|
62
src/axios.ts
62
src/axios.ts
|
@ -1,62 +0,0 @@
|
||||||
import { AxiosRequestConfig, Data, AxiosResponse, AxiosBaseInstance, AxiosInstance } from './types';
|
|
||||||
import Axios from './core/Axios';
|
|
||||||
import mergeConfig from './core/mergeConfig';
|
|
||||||
import CancelToken from './cancel/CancelToken';
|
|
||||||
import isCancel from './cancel/isCancel';
|
|
||||||
import defaults from './defaults';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建一个新的 Axios 实例
|
|
||||||
*
|
|
||||||
* 返回一个 Axios 实例增强
|
|
||||||
*/
|
|
||||||
function createInstance(defaults: AxiosRequestConfig): AxiosInstance {
|
|
||||||
const instance = new Axios(defaults);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支持重载的 axios 函数
|
|
||||||
*/
|
|
||||||
function axios<T extends Data>(
|
|
||||||
url: AxiosRequestConfig | string,
|
|
||||||
config: AxiosRequestConfig = {}
|
|
||||||
): Promise<AxiosResponse<T>> {
|
|
||||||
// 调用方式一处理请求配置
|
|
||||||
if (typeof url !== 'string') {
|
|
||||||
config = url;
|
|
||||||
}
|
|
||||||
// 调用方式二处理请求配置
|
|
||||||
else {
|
|
||||||
config = { ...config, url };
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance.request(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
// instance 的属性合并到 axios 函数中
|
|
||||||
Object.assign(axios, instance);
|
|
||||||
// instance 的方法合并到 axios 函数中
|
|
||||||
Object.setPrototypeOf(axios, Object.getPrototypeOf(instance));
|
|
||||||
|
|
||||||
return axios as AxiosInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Axios 实例拓展
|
|
||||||
*/
|
|
||||||
const axios = createInstance(defaults);
|
|
||||||
|
|
||||||
// 添加 create 工厂方法
|
|
||||||
axios.create = function create(defaults: AxiosRequestConfig = {}): AxiosBaseInstance {
|
|
||||||
return createInstance(mergeConfig(axios.defaults, defaults));
|
|
||||||
};
|
|
||||||
|
|
||||||
// 添加 Axios 类
|
|
||||||
axios.Axios = Axios;
|
|
||||||
|
|
||||||
// 添加 CancelToken 类
|
|
||||||
axios.CancelToken = CancelToken;
|
|
||||||
|
|
||||||
// 添加 检查错误是否来自取消请求 方法
|
|
||||||
axios.isCancel = isCancel;
|
|
||||||
|
|
||||||
export default axios;
|
|
|
@ -1,14 +0,0 @@
|
||||||
import { Cancel } from '../types';
|
|
||||||
|
|
||||||
export default class CancelClass implements Cancel {
|
|
||||||
/**
|
|
||||||
* @param message 取消信息
|
|
||||||
*/
|
|
||||||
public constructor(public message?: string) {}
|
|
||||||
|
|
||||||
public toString(): string {
|
|
||||||
const message = this.message ? `: ${this.message}` : '';
|
|
||||||
|
|
||||||
return `Cancel${message}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
import { CancelToken, CancelAction, CancelExecutor, CancelTokenSource } from '../types';
|
|
||||||
import Cancel from './Cancel';
|
|
||||||
|
|
||||||
export default class CancelTokenClass implements CancelToken {
|
|
||||||
/**
|
|
||||||
* 取消请求
|
|
||||||
*/
|
|
||||||
private _reason?: Cancel;
|
|
||||||
|
|
||||||
public listener: Promise<Cancel>;
|
|
||||||
|
|
||||||
public constructor(executor: CancelExecutor) {
|
|
||||||
let action!: CancelAction;
|
|
||||||
|
|
||||||
this.listener = new Promise<Cancel>((resolve) => {
|
|
||||||
action = (message) => {
|
|
||||||
// 防止重复取消
|
|
||||||
if (this._reason) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._reason = new Cancel(message);
|
|
||||||
|
|
||||||
resolve(this._reason);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
executor(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
public throwIfRequested(): void {
|
|
||||||
if (this._reason) {
|
|
||||||
throw this._reason;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回一个 CancelTokenSource
|
|
||||||
*
|
|
||||||
* CancelTokenSource.token 是一个 CancelToken 对象
|
|
||||||
*
|
|
||||||
* CancelTokenSource.cancel 是一个 CancelAction 函数
|
|
||||||
*
|
|
||||||
* 调用 CancelTokenSource.cancel('这里可以填写您的错误信息')
|
|
||||||
*
|
|
||||||
* 取消请求 CancelTokenSource.token
|
|
||||||
*/
|
|
||||||
public static source(): CancelTokenSource {
|
|
||||||
let cancel!: CancelAction;
|
|
||||||
|
|
||||||
const token = new CancelTokenClass(function executor(action) {
|
|
||||||
cancel = action;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
token,
|
|
||||||
cancel,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import Cancel from './Cancel';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否是取消请求实例
|
|
||||||
*
|
|
||||||
* @param value 判断的值
|
|
||||||
*/
|
|
||||||
export default function isCancel(value: unknown): value is Cancel {
|
|
||||||
return value instanceof Cancel;
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
import { Method, Params, Data, Interceptors, AxiosRequestConfig, AxiosResponse, Axios } from '../types';
|
|
||||||
import buildURL from '../helpers/buildURL';
|
|
||||||
import mergeConfig from './mergeConfig';
|
|
||||||
import InterceptorManager from './InterceptorManager';
|
|
||||||
import dispatchRequest from './dispatchRequest';
|
|
||||||
|
|
||||||
export default class AxiosClass implements Axios {
|
|
||||||
public interceptors: Interceptors = {
|
|
||||||
request: new InterceptorManager<AxiosRequestConfig>(),
|
|
||||||
response: new InterceptorManager<AxiosResponse>(),
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param defaults 自定义默认配置
|
|
||||||
*/
|
|
||||||
public constructor(public defaults: AxiosRequestConfig = {}) {}
|
|
||||||
|
|
||||||
public getUri(config: AxiosRequestConfig): string {
|
|
||||||
const { url = '', params, paramsSerializer } = mergeConfig(this.defaults, config);
|
|
||||||
|
|
||||||
return buildURL(url, params, paramsSerializer).replace(/^\?/, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
public request<T extends Data>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
|
|
||||||
const requestConfig = mergeConfig(this.defaults, config);
|
|
||||||
|
|
||||||
let promiseRequest = Promise.resolve(requestConfig);
|
|
||||||
|
|
||||||
// 执行请求拦截器
|
|
||||||
this.interceptors.request.forEach(function executor({ resolved, rejected }) {
|
|
||||||
promiseRequest = promiseRequest.then(resolved, rejected);
|
|
||||||
}, 'reverse');
|
|
||||||
|
|
||||||
// 发送请求
|
|
||||||
let promiseResponse = promiseRequest.then(dispatchRequest);
|
|
||||||
|
|
||||||
// 执行响应拦截器
|
|
||||||
this.interceptors.response.forEach(function executor({ resolved, rejected }) {
|
|
||||||
promiseResponse = promiseResponse.then(resolved, rejected);
|
|
||||||
});
|
|
||||||
|
|
||||||
return promiseResponse as Promise<AxiosResponse<T>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
public options<T extends Data>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
|
|
||||||
return this._requestMethodWithoutParams<T>('options', url, void 0, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get<T extends Data>(url: string, params?: Params, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
|
|
||||||
return this._requestMethodWithoutParams<T>('get', url, params, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
public head<T extends Data>(url: string, params?: Params, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
|
|
||||||
return this._requestMethodWithoutParams<T>('head', url, params, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
public post<T extends Data>(url: string, data?: Data, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
|
|
||||||
return this._requestMethodWithoutData<T>('post', url, data, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
public put<T extends Data>(url: string, data?: Data, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
|
|
||||||
return this._requestMethodWithoutData<T>('put', url, data, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
public delete<T extends Data>(url: string, params?: Params, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
|
|
||||||
return this._requestMethodWithoutParams<T>('delete', url, params, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
public trace<T extends Data>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
|
|
||||||
return this._requestMethodWithoutParams<T>('trace', url, void 0, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
public connect<T extends Data>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
|
|
||||||
return this._requestMethodWithoutParams<T>('connect', url, void 0, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 合并配置后发送 HTTP 请求
|
|
||||||
*
|
|
||||||
* @param method 请求方法
|
|
||||||
* @param url 请求地址
|
|
||||||
* @param params 请求参数
|
|
||||||
* @param config 额外配置
|
|
||||||
*/
|
|
||||||
private _requestMethodWithoutParams<T extends Data>(
|
|
||||||
method: Method,
|
|
||||||
url: string,
|
|
||||||
params?: Params,
|
|
||||||
config: AxiosRequestConfig = {}
|
|
||||||
): Promise<AxiosResponse<T>> {
|
|
||||||
return this.request<T>({
|
|
||||||
...config,
|
|
||||||
method,
|
|
||||||
url,
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 合并配置后发送 HTTP 请求
|
|
||||||
*
|
|
||||||
* @param method 请求方法
|
|
||||||
* @param url 请求地址
|
|
||||||
* @param data 请求数据
|
|
||||||
* @param config 额外配置
|
|
||||||
*/
|
|
||||||
private _requestMethodWithoutData<T extends Data>(
|
|
||||||
method: Method,
|
|
||||||
url: string,
|
|
||||||
data?: Data,
|
|
||||||
config: AxiosRequestConfig = {}
|
|
||||||
): Promise<AxiosResponse<T>> {
|
|
||||||
return this.request<T>({
|
|
||||||
...config,
|
|
||||||
method,
|
|
||||||
url,
|
|
||||||
data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
import {
|
|
||||||
InterceptorResolved,
|
|
||||||
InterceptorRejected,
|
|
||||||
Interceptor,
|
|
||||||
InterceptorExecutor,
|
|
||||||
InterceptorManager,
|
|
||||||
} from '../types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拦截器管理器
|
|
||||||
*/
|
|
||||||
export default class InterceptorManagerClass<T> implements InterceptorManager<T> {
|
|
||||||
/**
|
|
||||||
* 生成拦截器 id
|
|
||||||
*/
|
|
||||||
private _id = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拦截器集合
|
|
||||||
*/
|
|
||||||
private _interceptors: Record<number, Interceptor<T>> = {};
|
|
||||||
|
|
||||||
public use(resolved: InterceptorResolved<T>, rejected?: InterceptorRejected): number {
|
|
||||||
this._interceptors[++this._id] = {
|
|
||||||
resolved,
|
|
||||||
rejected,
|
|
||||||
};
|
|
||||||
|
|
||||||
return this._id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public eject(id: number): void {
|
|
||||||
delete this._interceptors[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
public forEach(executor: InterceptorExecutor<T>, reverse?: 'reverse'): void {
|
|
||||||
let interceptors: Interceptor<T>[] = Object.values(this._interceptors);
|
|
||||||
|
|
||||||
if (reverse === 'reverse') {
|
|
||||||
interceptors = interceptors.reverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
interceptors.forEach(executor);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
import { AxiosRequestConfig, RequestConfig, AxiosResponse, AxiosError } from '../types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AxiosError 继承自 Error
|
|
||||||
*/
|
|
||||||
class AxiosErrorClass extends Error implements AxiosError {
|
|
||||||
public isAxiosError = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param message 错误信息
|
|
||||||
* @param config Axios 请求配置
|
|
||||||
* @param request 通用请求配置
|
|
||||||
* @param response Axios 响应体
|
|
||||||
*/
|
|
||||||
public constructor(
|
|
||||||
message: string,
|
|
||||||
public config: AxiosRequestConfig,
|
|
||||||
public request: RequestConfig,
|
|
||||||
public response?: AxiosResponse
|
|
||||||
) {
|
|
||||||
super(message);
|
|
||||||
|
|
||||||
// 修复继承系统自带类 prototype 设置失败的问题
|
|
||||||
Object.setPrototypeOf(this, AxiosErrorClass.prototype);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 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 {
|
|
||||||
return new AxiosErrorClass(message, config, request, response);
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
import { AxiosRequestConfig, AxiosResponse } from '../types';
|
|
||||||
import isCancel from '../cancel/isCancel';
|
|
||||||
import flattenHeaders from './flattenHeaders';
|
|
||||||
import transformData from './transformData';
|
|
||||||
import request from './request';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 如果已经取消, 则抛出取消对象
|
|
||||||
*
|
|
||||||
* @param config Axios 请求配置
|
|
||||||
*/
|
|
||||||
function throwIfCancellationRequested(config: AxiosRequestConfig) {
|
|
||||||
if (config.cancelToken) {
|
|
||||||
config.cancelToken.throwIfRequested();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送请求
|
|
||||||
*
|
|
||||||
* @param config Axios 请求配置
|
|
||||||
*/
|
|
||||||
export default function dispatchRequest(config: AxiosRequestConfig): Promise<AxiosResponse> {
|
|
||||||
throwIfCancellationRequested(config);
|
|
||||||
|
|
||||||
config.headers = flattenHeaders(config);
|
|
||||||
|
|
||||||
config.data = transformData(config.data ?? {}, config.headers, config.transformRequest);
|
|
||||||
|
|
||||||
function onResolved(response: AxiosResponse): AxiosResponse {
|
|
||||||
throwIfCancellationRequested(config);
|
|
||||||
|
|
||||||
response.data = transformData(response.data, response.headers, config.transformResponse);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRejected(reason: any): Promise<any> {
|
|
||||||
if (!isCancel(reason)) {
|
|
||||||
throwIfCancellationRequested(config);
|
|
||||||
|
|
||||||
if (reason.response !== void 0) {
|
|
||||||
reason.response.data = transformData(reason.response.data, reason.response.headers, config.transformResponse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return config.errorHandler?.(reason) ?? Promise.reject(reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
return request(config).then(onResolved, onRejected);
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
import { Headers, AxiosRequestConfig } from '../types';
|
|
||||||
import { omit } from '../helpers/utils';
|
|
||||||
import { methodToLowercase } from './transformMethod';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拉平请求头
|
|
||||||
*
|
|
||||||
* @param config Axios 请求配置
|
|
||||||
*/
|
|
||||||
export default function flattenHeaders(config: AxiosRequestConfig): Headers {
|
|
||||||
const { headers } = config;
|
|
||||||
|
|
||||||
if (headers === void 0) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const method = methodToLowercase(config.method);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...(headers.common ?? {}),
|
|
||||||
...(headers[method] ?? {}),
|
|
||||||
...omit(headers, 'common', 'options', 'get', 'head', 'post', 'put', 'delete', 'trace', 'connect'),
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,122 +0,0 @@
|
||||||
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 中的配置
|
|
||||||
*
|
|
||||||
* @param keys
|
|
||||||
* @param config
|
|
||||||
* @param config2
|
|
||||||
*/
|
|
||||||
function onlyFromConfig2(keys: OnlyFromConfig2Key[], config: AxiosRequestConfig, config2: AxiosRequestConfig) {
|
|
||||||
keys.forEach((key) => {
|
|
||||||
if (config2[key] !== void 0) {
|
|
||||||
config[key] = config2[key] as any;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 优先取 config2 中的配置, config2 中没有就取 config1
|
|
||||||
*
|
|
||||||
* @param keys
|
|
||||||
* @param config
|
|
||||||
* @param config1
|
|
||||||
* @param config2
|
|
||||||
*/
|
|
||||||
function priorityFromConfig2(
|
|
||||||
keys: PriorityFromConfig2Key[],
|
|
||||||
config: AxiosRequestConfig,
|
|
||||||
config1: AxiosRequestConfig,
|
|
||||||
config2: AxiosRequestConfig
|
|
||||||
) {
|
|
||||||
keys.forEach((key) => {
|
|
||||||
if (config2[key] !== void 0) {
|
|
||||||
config[key] = config2[key] as any;
|
|
||||||
} else if (config1[key] !== void 0) {
|
|
||||||
config[key] = config1[key] as any;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 深度合并配置
|
|
||||||
*
|
|
||||||
* @param keys
|
|
||||||
* @param config
|
|
||||||
* @param config1
|
|
||||||
* @param config2
|
|
||||||
*/
|
|
||||||
function deepMergeConfig(
|
|
||||||
keys: DeepMergeConfigKey[],
|
|
||||||
config: AxiosRequestConfig,
|
|
||||||
config1: AxiosRequestConfig,
|
|
||||||
config2: AxiosRequestConfig
|
|
||||||
) {
|
|
||||||
keys.forEach((key) => {
|
|
||||||
if (isPlainObject(config2[key])) {
|
|
||||||
config[key] = deepMerge(config1[key] ?? {}, config2[key] as AnyObject);
|
|
||||||
} else if (isPlainObject(config1[key])) {
|
|
||||||
config[key] = deepMerge(config1[key] as AnyObject);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 合并 Axios 请求配置
|
|
||||||
*
|
|
||||||
* @param config1 Axios 请求配置1
|
|
||||||
* @param config2 Axios 请求配置2
|
|
||||||
*/
|
|
||||||
export default function mergeConfig(
|
|
||||||
config1: AxiosRequestConfig = {},
|
|
||||||
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(onlyFromConfig2Keys, config, config2);
|
|
||||||
priorityFromConfig2(priorityFromConfig2Keys, config, config1, config2);
|
|
||||||
deepMergeConfig(deepMergeConfigKeys, config, config1, config2);
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
import { AxiosRequestConfig, AxiosResponse, Response } from '../types';
|
|
||||||
import transformRequest from './transformRequest';
|
|
||||||
import transformResponse from './transformResponse';
|
|
||||||
import createError from './createError';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求函数
|
|
||||||
*
|
|
||||||
* @param config Axios 请求配置
|
|
||||||
*/
|
|
||||||
export default function request(config: AxiosRequestConfig): Promise<AxiosResponse> {
|
|
||||||
return new Promise(function dispatchAdapter(resolve, reject): void {
|
|
||||||
const { adapter, cancelToken } = config;
|
|
||||||
const requestConfig = transformRequest(config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 捕获错误
|
|
||||||
*
|
|
||||||
* @param message 错误信息
|
|
||||||
* @param response Axios 响应体
|
|
||||||
*/
|
|
||||||
function catchError(message: any, response?: AxiosResponse): void {
|
|
||||||
if (typeof message !== 'string') {
|
|
||||||
message = '配置不正确或者网络异常';
|
|
||||||
}
|
|
||||||
|
|
||||||
reject(createError(message, config, requestConfig, response));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adapter === void 0) {
|
|
||||||
catchError('平台适配失败,您需要参阅文档使用自定义适配器手动适配当前平台');
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 效验状态码
|
|
||||||
*
|
|
||||||
* @param res 请求结果
|
|
||||||
*/
|
|
||||||
function handleResponse(res: Response): void {
|
|
||||||
const response = transformResponse(res, config);
|
|
||||||
|
|
||||||
if (config.validateStatus === void 0 || config.validateStatus(response.status)) {
|
|
||||||
resolve(response);
|
|
||||||
} else {
|
|
||||||
catchError(`请求失败,状态码为 ${response.status}`, response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用适配器发送请求
|
|
||||||
const task = adapter({
|
|
||||||
...requestConfig,
|
|
||||||
success: handleResponse,
|
|
||||||
fail: catchError,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 如果存在取消令牌
|
|
||||||
// 则调用取消令牌里的 listener 监听用户的取消操作
|
|
||||||
if (cancelToken !== void 0) {
|
|
||||||
cancelToken.listener.then(function onCanceled(reason): void {
|
|
||||||
if (task !== void 0) {
|
|
||||||
task.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
reject(reason);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,28 +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 {
|
|
||||||
if (transforms === void 0) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(transforms)) {
|
|
||||||
transforms = [transforms];
|
|
||||||
}
|
|
||||||
|
|
||||||
transforms.forEach((transform: TransformData) => {
|
|
||||||
data = transform(data, headers);
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
import { AliasMethod, AdapterMethod, Method } from '../types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求方法转全小写
|
|
||||||
*
|
|
||||||
* @param config Axios 请求配置
|
|
||||||
*/
|
|
||||||
export function methodToLowercase(method: Method = 'get'): AliasMethod {
|
|
||||||
return method.toLowerCase() as AliasMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求方法转全大写
|
|
||||||
*
|
|
||||||
* @param config Axios 请求配置
|
|
||||||
*/
|
|
||||||
export function methodToUppercase(method: Method = 'GET'): AdapterMethod {
|
|
||||||
return method.toUpperCase() as AdapterMethod;
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
import { AxiosRequestConfig, RequestConfig } from '../types';
|
|
||||||
import { pick } from '../helpers/utils';
|
|
||||||
import isAbsoluteURL from '../helpers/isAbsoluteURL';
|
|
||||||
import combineURL from '../helpers/combineURL';
|
|
||||||
import buildURL from '../helpers/buildURL';
|
|
||||||
import { methodToUppercase } from './transformMethod';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据配置中的 baseURL 和 url 和 params 生成完整 URL
|
|
||||||
*
|
|
||||||
* @param config Axios 请求配置
|
|
||||||
*/
|
|
||||||
function transformURL(config: AxiosRequestConfig): string {
|
|
||||||
const { baseURL = '', url = '' } = config;
|
|
||||||
const fullURL = isAbsoluteURL(url) ? url : combineURL(baseURL, url);
|
|
||||||
|
|
||||||
return buildURL(fullURL, config.params, config.paramsSerializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Axios 请求配置转换成各大平台通用请求配置
|
|
||||||
*
|
|
||||||
* 抹平差异
|
|
||||||
*
|
|
||||||
* @param config Axios 请求配置
|
|
||||||
*/
|
|
||||||
export default function transformRequest(config: AxiosRequestConfig): RequestConfig {
|
|
||||||
return {
|
|
||||||
url: transformURL(config),
|
|
||||||
|
|
||||||
method: methodToUppercase(config.method),
|
|
||||||
|
|
||||||
header: config.headers,
|
|
||||||
|
|
||||||
...pick(
|
|
||||||
config,
|
|
||||||
'data',
|
|
||||||
'headers',
|
|
||||||
'dataType',
|
|
||||||
'responseType',
|
|
||||||
'timeout',
|
|
||||||
'enableHttp2',
|
|
||||||
'enableQuic',
|
|
||||||
'enableCache',
|
|
||||||
'sslVerify'
|
|
||||||
),
|
|
||||||
} as RequestConfig;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
import { AxiosRequestConfig, AxiosResponse, Response } from '../types';
|
|
||||||
import { pick } from '../helpers/utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 各大平台通用响应体转成 Axios 响应体
|
|
||||||
*
|
|
||||||
* 抹平差异
|
|
||||||
*
|
|
||||||
* @param response 通用响应体
|
|
||||||
* @param config Axios 请求配置
|
|
||||||
*/
|
|
||||||
export default function transformResponse(response: Response, config: AxiosRequestConfig): AxiosResponse {
|
|
||||||
const status = response.statusCode ?? response.status ?? 400;
|
|
||||||
|
|
||||||
const headers = response.header ?? response.headers ?? {};
|
|
||||||
|
|
||||||
const statusText = status === 200 ? 'OK' : status === 400 ? 'Bad Adapter' : '';
|
|
||||||
|
|
||||||
return {
|
|
||||||
status,
|
|
||||||
statusText,
|
|
||||||
headers,
|
|
||||||
config,
|
|
||||||
...pick(response, 'data', 'cookies', 'profile'),
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
import { AxiosRequestConfig } from './types';
|
|
||||||
import adaptive from './adaptive';
|
|
||||||
|
|
||||||
const defaults: AxiosRequestConfig = {
|
|
||||||
/**
|
|
||||||
* 适配器
|
|
||||||
*/
|
|
||||||
adapter: adaptive(),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求方法
|
|
||||||
*/
|
|
||||||
method: 'get',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求头
|
|
||||||
*/
|
|
||||||
headers: {
|
|
||||||
common: {
|
|
||||||
Accept: 'application/json, test/plain, */*',
|
|
||||||
},
|
|
||||||
options: {},
|
|
||||||
get: {},
|
|
||||||
head: {},
|
|
||||||
post: {
|
|
||||||
'Context-Type': 'application/x-www-form-urlencoded; charset=utf-8',
|
|
||||||
},
|
|
||||||
put: {
|
|
||||||
'Context-Type': 'application/x-www-form-urlencoded; charset=utf-8',
|
|
||||||
},
|
|
||||||
delete: {},
|
|
||||||
trace: {},
|
|
||||||
connect: {},
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 状态码效验
|
|
||||||
*
|
|
||||||
* @param status 状态码
|
|
||||||
*/
|
|
||||||
validateStatus: function validateStatus(status: number): boolean {
|
|
||||||
return status >= 200 && status < 300;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超时时间
|
|
||||||
*/
|
|
||||||
timeout: 10000,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 响应数据格式
|
|
||||||
*/
|
|
||||||
dataType: 'json',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 响应数据类型
|
|
||||||
*/
|
|
||||||
responseType: 'text',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开启 http2
|
|
||||||
*/
|
|
||||||
enableHttp2: false,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开启 quic
|
|
||||||
*/
|
|
||||||
enableQuic: false,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开启 cache
|
|
||||||
*/
|
|
||||||
enableCache: false,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证 ssl 证书
|
|
||||||
*/
|
|
||||||
sslVerify: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default defaults;
|
|
|
@ -1,74 +0,0 @@
|
||||||
import { AnyObject, Params } from '../types';
|
|
||||||
import { encode, isPlainObject, isDate } from './utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过请求地址和序列化参数生成新的请求地址
|
|
||||||
*
|
|
||||||
* @param url 请求地址
|
|
||||||
* @param serializedParams 序列化参数
|
|
||||||
*/
|
|
||||||
function generateURL(url: string, serializedParams: string): string {
|
|
||||||
// 移除 hash
|
|
||||||
const hashIndex = url.indexOf('#');
|
|
||||||
|
|
||||||
if (hashIndex !== -1) {
|
|
||||||
url = url.slice(0, hashIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serializedParams === '') {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 拼接前缀
|
|
||||||
const prefix = url.indexOf('?') === -1 ? '?' : '&';
|
|
||||||
|
|
||||||
serializedParams = `${prefix}${serializedParams}`;
|
|
||||||
|
|
||||||
return `${url}${serializedParams}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认参数序列化
|
|
||||||
*
|
|
||||||
* @param params 请求参数
|
|
||||||
*/
|
|
||||||
function paramsSerialization(params: AnyObject): string {
|
|
||||||
const parts: string[] = [];
|
|
||||||
|
|
||||||
Object.entries(params).forEach(function encodeKeyValue([key, value]): void {
|
|
||||||
if (value === null || value === void 0 || value !== value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果值是一个数组, 则特殊处理 key
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
key += '[]';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转成数组统一处理
|
|
||||||
const values: any[] = [].concat(value);
|
|
||||||
|
|
||||||
values.forEach((val: any): void => {
|
|
||||||
if (isPlainObject(val)) {
|
|
||||||
val = JSON.stringify(val);
|
|
||||||
} else if (isDate(val)) {
|
|
||||||
val = val.toISOString();
|
|
||||||
}
|
|
||||||
|
|
||||||
parts.push(`${encode(key)}=${encode(val)}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return parts.join('&');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理 URL 参数
|
|
||||||
*
|
|
||||||
* @param url 请求地址
|
|
||||||
* @param params 请求参数
|
|
||||||
* @param paramsSerializer 自定义参数序列化
|
|
||||||
*/
|
|
||||||
export default function buildURL(url: string, params: Params = {}, paramsSerializer = paramsSerialization): string {
|
|
||||||
return generateURL(url, paramsSerializer(params));
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
/**
|
|
||||||
* 拼接 baseURL 和 url 获得完整的 URL
|
|
||||||
*
|
|
||||||
* combineURL('1/2///','////3/4') => '1/2/3/4'
|
|
||||||
*/
|
|
||||||
export default function combineURL(baseURL: string, url: string): string {
|
|
||||||
return `${baseURL.replace(/\/*$/, '')}/${url.replace(/^\/*/, '')}`;
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
/**
|
|
||||||
* 检查是否是一个绝对 URL
|
|
||||||
*
|
|
||||||
* xxx:// 或者 "//" 开头, 视为绝对地址
|
|
||||||
*
|
|
||||||
* @param url 需要检查的 URL
|
|
||||||
*/
|
|
||||||
export default function isAbsoluteURL(url: string): boolean {
|
|
||||||
return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
import { AnyObject } from '../types';
|
|
||||||
|
|
||||||
const _toString = Object.prototype.toString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对字符串进行编码转换
|
|
||||||
*
|
|
||||||
* @param str 字符串
|
|
||||||
*/
|
|
||||||
export function encode(str: string): string {
|
|
||||||
return encodeURIComponent(str)
|
|
||||||
.replace(/%40/gi, '@')
|
|
||||||
.replace(/%3A/gi, ':')
|
|
||||||
.replace(/%24/g, '$')
|
|
||||||
.replace(/%2C/gi, ',')
|
|
||||||
.replace(/%20/g, '+')
|
|
||||||
.replace(/%5B/gi, '[')
|
|
||||||
.replace(/%5D/gi, ']');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是不是一个日期对象
|
|
||||||
*
|
|
||||||
* @param date 判断目标
|
|
||||||
*/
|
|
||||||
export function isDate(date: unknown): date is Date {
|
|
||||||
return _toString.call(date) === '[object Date]';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是不是一个普通对象
|
|
||||||
*
|
|
||||||
* @param obj 判断目标
|
|
||||||
*/
|
|
||||||
export function isPlainObject(obj: unknown): obj is Record<string, unknown> {
|
|
||||||
return _toString.call(obj) === '[object Object]';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 深度合并多个对象
|
|
||||||
*
|
|
||||||
* @param objs n 个对象
|
|
||||||
*/
|
|
||||||
export function deepMerge(...objs: Record<string, any>[]): Record<string, any> {
|
|
||||||
const result: Record<string, any> = {};
|
|
||||||
|
|
||||||
function assignValue(key: string, val: any) {
|
|
||||||
// 如果当前结果和当前值都为普通对象
|
|
||||||
// 递归进行深度合并
|
|
||||||
if (isPlainObject(result[key]) && isPlainObject(val)) {
|
|
||||||
result[key] = deepMerge(result[key], val);
|
|
||||||
}
|
|
||||||
// 如果只有当前值为普通对象
|
|
||||||
// 直接深拷贝当前值
|
|
||||||
else if (isPlainObject(val)) {
|
|
||||||
result[key] = deepMerge({}, val);
|
|
||||||
}
|
|
||||||
// 如果都不是普通对象
|
|
||||||
// 直接赋值
|
|
||||||
else {
|
|
||||||
result[key] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
objs.forEach(function assignObj(obj: Record<string, any>): void {
|
|
||||||
Object.entries(obj).forEach(function assignKey([key, value]) {
|
|
||||||
assignValue(key, value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从对象中提取一部分属性
|
|
||||||
*
|
|
||||||
* @param obj 源对象
|
|
||||||
* @param keys 需要提取的 key
|
|
||||||
*/
|
|
||||||
export function pick<T extends AnyObject, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> {
|
|
||||||
const _pick: Partial<T> = {};
|
|
||||||
|
|
||||||
keys.forEach(function pickKey(key: K) {
|
|
||||||
_pick[key] = obj[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
return _pick as Pick<T, K>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从对象中剔除一部分属性
|
|
||||||
*
|
|
||||||
* @param obj 源对象
|
|
||||||
* @param keys 需要剔除的 key
|
|
||||||
*/
|
|
||||||
export function omit<T extends AnyObject, K extends keyof T>(obj: T, ...keys: K[]): Omit<T, K> {
|
|
||||||
const _omit = { ...obj };
|
|
||||||
|
|
||||||
keys.forEach(function omitKey(key: K) {
|
|
||||||
delete _omit[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
return _omit;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
import axios from './axios';
|
|
||||||
|
|
||||||
export * from './types';
|
|
||||||
|
|
||||||
export default axios;
|
|
699
src/types.ts
699
src/types.ts
|
@ -1,699 +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;
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "esnext",
|
|
||||||
"module": "esnext",
|
|
||||||
"lib": [
|
|
||||||
"es2020"
|
|
||||||
],
|
|
||||||
"declaration": true,
|
|
||||||
"declarationDir": "./types",
|
|
||||||
"sourceMap": true,
|
|
||||||
"removeComments": false,
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"baseUrl": "./",
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"./src/**/*"
|
|
||||||
]
|
|
||||||
}
|
|
Loading…
Reference in New Issue