feat: 从参数中删除动态地址属性

pull/49/head
zjx0905 2023-04-17 21:31:03 +08:00
parent b5730304ba
commit b0eaa04c66
14 changed files with 274 additions and 23 deletions

View File

@ -140,7 +140,7 @@ axios.defaults.adapter = (config) => {
fail: (error) => {
config.fail({
// 状态码
status: '400',
status: 400,
// 状态文本
statusText: 'Fail Adapter',
@ -185,7 +185,7 @@ axios.defaults.adapter = (config) => {
fail: (error) => {
config.fail({
// 状态码
status: '400',
status: 400,
// 状态文本
statusText: 'Fail Adapter',
@ -226,7 +226,7 @@ axios.defaults.adapter = (config) => {
fail: (error) => {
config.fail({
// 状态码
status: '400',
status: 400,
// 状态文本
statusText: 'Fail Adapter',
@ -259,7 +259,7 @@ axios.defaults.adapter = axios.createAdapter({
});
```
可以进一步抹平存在差异的部分,实现完美适配全平台。
可以进一步抹平存在差异的部分,实现完美适配全平台。
```ts
import axios from 'axios-miniprogram';

View File

@ -80,3 +80,36 @@ const ejectId = axios.interceptors.request.use(
// 移除请求拦截器
axios.interceptors.request.eject(ejectId);
```
## 移除所有请求拦截器
可以移除所有请求拦截器。
```ts
import axios from 'axios-miniprogram';
axios.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
},
);
axios.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
},
);
// 移除所有请求拦截器
axios.interceptors.request.clear();
```

View File

@ -80,3 +80,36 @@ const ejectId = axios.interceptors.response.use(
// 移除响应拦截器
axios.interceptors.response.eject(ejectId);
```
## 移除所有响应拦截器
可以移除所有响应拦截器。
```ts
import axios from 'axios-miniprogram';
axios.interceptors.request.use(
function (response) {
// 在 then 之前做些什么
return response;
},
function (error) {
// 在 catch 之前做些什么
return Promise.reject(error);
},
);
axios.interceptors.request.use(
function (response) {
// 在 then 之前做些什么
return response;
},
function (error) {
// 在 catch 之前做些什么
return Promise.reject(error);
},
);
// 移除所有响应拦截器
axios.interceptors.request.clear();
```

View File

@ -57,7 +57,7 @@ title: 默认配置
可以给属性设置默认值。
部分示例:
列举部分示例:
```ts
import axios from 'axios-miniprogram';

View File

@ -8,4 +8,93 @@ title: 动态地址
简化设置地址参数。
:::
未完待续...
## 设置 `params` 动态参数
可以设置属性 `params`,最终会从 `params` 中获取到对应的值。
::: warning 注意
获取到值之后,会从 `params` 中删除对应的属性。
:::
```ts
import axios from 'axios-miniprogram';
// 请求的服务端地址 https://api.com/1
// 获取到 id 之后,会从 params 中删除 id
axios('https://api.com/:id', {
params: {
id: 1,
},
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
```
## 设置 `data` 动态参数
可以设置属性 `data`,最终会从 `data` 中获取到对应的值。
```ts
import axios from 'axios-miniprogram';
// 请求的服务端地址 https://api.com/1
// 获取到 id 之后,不会从 data 中删除 id
axios('https://api.com/:id', {
method: 'POST',
data: {
id: 1,
},
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
```
## 同时设置 `params``data`
可以同时设置 `params``data`,会优先从 `params` 中获取对应的值。
```ts
import axios from 'axios-miniprogram';
// 请求的服务端地址 https://api.com/1
axios('https://api.com/:id', {
method: 'POST',
params: {
id: 1,
},
data: {
id: 2,
},
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
// 请求的服务端地址 https://api.com/1/2
axios('https://api.com/:id1/:id2', {
method: 'POST',
params: {
id1: 1,
},
data: {
id2: 2,
},
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
```

View File

@ -116,3 +116,42 @@ axios('https://api.com/test', {
// 失败之后做些什么
});
```
## 全局错误处理
可以把 `errorHandler` 设置到默认配置中,每一个请求都可以进行错误处理。
```ts
import axios from 'axios-miniprogram';
// 全局错误处理
axios.defaults.errorHandler = (error) => {
if (axios.isAxiosError(error)) {
// 响应错误
const {
// 错误消息
message,
// 请求配置
config,
// 请求任务,也就是请求函数返回的结果
request,
// 响应体
response,
} = error;
if (response.isFail) {
// 平台或适配器错误
} else {
// 使用 `validateStatus` 自定义抛出的错误
}
} else if (axios.isCancel(error)) {
// 取消请求
} else {
// 其他错误
}
};
```

View File

@ -8,4 +8,25 @@ title: 参数系列化
支持自定义参数系列化器。
:::
未完待续...
## 自定义参数系列化器
可以用自己的方式对参数进行系列化。
```ts
import axios from 'axios-miniprogram';
axios('https://api.com', {
params: {
id: 1,
},
paramsSerializer(params) {
return qs.stringify(params);
},
})
.then((response) => {
// 请求成功后做些什么
})
.catch((error) => {
// 请求失败后做些什么
});
```

View File

@ -8,7 +8,7 @@ export function transformURL(config: AxiosRequestConfig) {
let url = config.url ?? '';
if (!isAbsoluteURL(url)) url = combineURL(config.baseURL ?? '', url);
url = dynamicURL(url, Object.assign({}, config.params, config.data));
url = dynamicURL(url, config.params, config.data);
url = buildURL(url, config.params, config.paramsSerializer);
return url;

View File

@ -1,4 +1,14 @@
const dynamicRE = /\/:([^/]+)/g;
export function dynamicURL(url: string, data: AnyObject) {
return url.replace(dynamicRE, (_, $2) => `/${data[$2]}`);
export function dynamicURL(
url: string,
params: AnyObject = {},
data: AnyObject = {},
) {
return url.replace(dynamicRE, (_, $2) => {
const value = params[$2] ?? data[$2];
if ($2 in params) {
delete params[$2];
}
return `/${value}`;
});
}

View File

@ -9,7 +9,7 @@ describe('src/axios.ts', () => {
headers: { type: 'json' },
data: { v1: 1 },
before: (config) => {
expect(config.url).toBe('http://api.com/test/1?id=1');
expect(config.url).toBe('http://api.com/test/1');
},
}),
baseURL: 'http://api.com',

View File

@ -68,8 +68,8 @@ describe('src/core/Axios.ts', () => {
const c2 = {
adapter: mockAdapter({
before: (config) => {
expect(config.url).toBe('http://api.com/test/1?id=1');
expect(config.params).toEqual(p);
expect(config.url).toBe('http://api.com/test/1');
expect(config.params).toEqual({});
},
data,
}),
@ -79,7 +79,7 @@ describe('src/core/Axios.ts', () => {
axios[a]('test', p, c1).then((res) => {
expect(res.data).toEqual(data);
});
axios[a]('test/:id', p, c2).then((res) => {
axios[a]('test/:id', { ...p }, c2).then((res) => {
expect(res.data).toEqual(data);
});
});

View File

@ -99,7 +99,7 @@ describe('src/core/dispatchRequest.ts', () => {
dispatchRequest(c3);
expect(c1.url).toBe('http://api.com/test');
expect(c2.url).toBe('http://api.com/test/1?id=1');
expect(c2.url).toBe('http://api.com/test/1');
expect(c3.url).toBe('http://api.com/test/1');
});

View File

@ -42,7 +42,7 @@ describe('src/core/transformURL.ts', () => {
type: 0,
},
}),
).toBe('http://api.com/test/axios/0?name=axios&type=0');
).toBe('http://api.com/test/axios/0');
expect(
transformURL({
baseURL: 'http://api.com',

View File

@ -2,22 +2,48 @@ import { describe, test, expect } from 'vitest';
import { dynamicURL } from '@/helpers/dynamicURL';
describe('src/helpers/dynamicURL.ts', () => {
test('应该替换关键字', () => {
test('应该支持空参数', () => {
expect(dynamicURL('http://api.com/test/:id')).toBe(
'http://api.com/test/undefined',
);
expect(dynamicURL('http://api.com/test/:id', {})).toBe(
'http://api.com/test/undefined',
);
expect(dynamicURL('http://api.com/test/:id', undefined, {})).toBe(
'http://api.com/test/undefined',
);
});
test('应该支持 params', () => {
expect(dynamicURL('http://api.com/test/:id', { id: 1 })).toBe(
'http://api.com/test/1',
);
});
test('应该支持多个关键字', () => {
test('应该支持 data', () => {
expect(dynamicURL('http://api.com/test/:id', {}, { id: 1 })).toBe(
'http://api.com/test/1',
);
});
test('应该优先从 params 取值', () => {
expect(dynamicURL('http://api.com/test/:id', { id: 1 }, { id: 2 })).toBe(
'http://api.com/test/1',
);
expect(
dynamicURL('http://api.com/tests/name/:name/type/:type/list', {
name: 'axios',
type: 0,
}),
).toBe('http://api.com/tests/name/axios/type/0/list');
dynamicURL('http://api.com/test/:id1/:id2', { id1: 1 }, { id2: 2 }),
).toBe('http://api.com/test/1/2');
});
test('应该从 params 删除对应的值', () => {
const p = { id1: 1 };
const d = { id2: 2 };
expect(dynamicURL('http://api.com/test/:id1/:id2', p, d)).toBe(
'http://api.com/test/1/2',
);
expect(p.id1).toBeUndefined();
expect(d.id2).toBe(2);
});
test('应该忽略端口号', () => {