feat: 废弃 fork API

BREAKING CHANGE :
axios.fork() 已废弃
pull/49/head
zjx0905 2023-08-12 22:08:44 +08:00
parent 158d26fa64
commit a04f833d91
13 changed files with 63 additions and 307 deletions

View File

@ -123,7 +123,6 @@ function sidebar() {
{ text: '创建实例', link: '/advanced/instance' },
{ text: '扩展实例', link: '/advanced/extend' },
{ text: '平台适配器', link: '/advanced/adapter' },
{ text: '派生领域(即将废弃)', link: '/advanced/fork' },
],
collapsed: false,
},

View File

@ -20,7 +20,7 @@ import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
// 相对地址会进行组合
// baseURL 最终结果为 https://api.com/uesr
// baseURL 最终结果为 https://api.com/user
const instance = axios.extend({
baseURL: 'user',
headers: {

View File

@ -1,228 +0,0 @@
---
title: 派生领域
---
# {{ $frontmatter.title }}
::: tip {{ $frontmatter.title }}
派生新的领域简化 `URL`
:::
::: warning 注意
该接口即将废弃,请使用功能更强的[扩展实例](./extend)。
:::
## 派生领域
可以基于 `axios` 派生领域,配置项 `baseURL` 传相对地址时会和 `axios.defaults.baseURL` 一起组合成完整的服务端地址。
全局默认配置 `axios.defaults` 和派生领域时传入的配置 `config` 将会按优先级[合并](/basics/defaults#配置合并策略)成领域默认配置 `domain.defaults`
```ts
import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
// 相对地址会进行组合
// baseURL 最终结果为 https://api.com/uesr
const domain = axios.fork({
baseURL: 'user',
headers: {
common: {
['Content-Type']: 'application/json',
},
post: {
['Content-Type']: 'application/x-www-form-urlencoded',
},
},
timeout: 1000,
});
// 绝对地址会直接使用
// baseURL 最终结果为 https://api2.com/user
const domain = axios.fork({
baseURL: 'https://api2.com/user',
headers: {
common: {
['Content-Type']: 'application/json',
},
post: {
['Content-Type']: 'application/x-www-form-urlencoded',
},
},
timeout: 1000,
});
```
## 默认配置
可以设置配置项默认值。
```ts
import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
const domain = axios.fork({
baseURL: 'user',
});
domain.defaults.headers.common['Content-Type'] = 'application/json';
domain.defaults.timeout = 1000;
```
## 拦截器
可以使用父级的拦截器,但不支持为领域单独添加拦截器。
基于 axios 派生领域。
```ts
import axios from 'axios-miniprogram';
// 请求拦截器
axios.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
},
);
// 响应拦截器
axios.interceptors.response.use(
function (response) {
// 在 then 之前做些什么
return response;
},
function (error) {
// 在 catch 之前做些什么
return Promise.reject(error);
},
);
const domain = axios.fork({
baseURL: 'test',
});
// 发送请求时会使用 axios 的请求拦截器和响应拦截器
domain.get('/');
```
基于实例派生领域。
```ts
import axios from 'axios-miniprogram';
const instance = axios.create({
baseURL: 'https://api.com',
});
// 请求拦截器
instance.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
},
);
// 响应拦截器
instance.interceptors.response.use(
function (response) {
// 在 then 之前做些什么
return response;
},
function (error) {
// 在 catch 之前做些什么
return Promise.reject(error);
},
);
const domain = instance.fork({
baseURL: 'test',
});
// 发送请求时会使用 instance 的请求拦截器和响应拦截器
domain.get('/');
```
## 使用方式
可以使用请求方法发送请求。
```ts
import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
const domain = axios.fork({
baseURL: 'user',
});
// 请求的服务端地址 https://api.com/uesr/1
domain
.get('/:id', {
id: 1,
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
// 请求的服务端地址 https://api.com/uesr
domain
.post('/', {
id: 1,
name: 'user',
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
// 请求的服务端地址 https://api.com/uesr/1
domain
.put('/:id', {
name: 'user',
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
// 请求的服务端地址 https://api.com/uesr/1
domain
.delete('/:id', {
id: 1,
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
```
- [domain.request(url, config?) | domain.request(config)](/basics/request)
- [domain.options(url, config?)](/method/OPTIONS)
- [domain.get(url, params?, config?)](/method/GET)
- [domain.head(url, params?, config?)](/method/HEAD)
- [domain.post(url, data?, config?)](/method/POST)
- [domain.put(url, data?, config?)](/method/PUT)
- [domain.patch(url, data?, config?)](/method/PATCH)
- [domain.delete(url, params?, config?)](/method/DELETE)
- [domain.trace(url, config?)](/method/TRACE)
- [domain.connect(url, config?)](/method/CONNECT)

View File

@ -99,7 +99,7 @@ const child = instance.extend({
baseURL: 'user',
});
// 请求的服务端地址 https://api2.com/uesr
// 请求的服务端地址 https://api2.com/user
child('/');
```

View File

@ -11,9 +11,10 @@ title: 中间件
## 前言
如果您了解或者使用过[koa](https://github.com/koajs/koa),相信您一定十分了解什么是洋葱模型,中间件该怎么写。
中间件是一个异步函数,接收 `context``next` 两个参数。
`context` 是一个对象,提供了 `req` 对象和 `res` 对象作为其成部分。
`context` 是一个对象,提供了 `req` 对象和 `res` 对象作为其成部分。
- `context.req`:请求配置。
- `context.res`:请求完成后服务端返回的响应体,它的初始值是 `null`,请求完成之后才能对其进行操作。
@ -117,6 +118,6 @@ instance.use(async (ctx, next) => {
});
// 复用父级中间件
// axios request -> instance request -> https://api.com/test/uesr -> instance response -> axios response
// axios request -> instance request -> https://api.com/test/user -> instance response -> axios response
instance('/user');
```

View File

@ -1,6 +1,6 @@
import { isFunction, isPlainObject } from '../helpers/types';
import { assert } from '../helpers/error';
import { origIgnore } from '../helpers/ignore';
import { orgIgnore } from '../helpers/ignore';
import {
AxiosProgressEvent,
AxiosRequestFormData,
@ -281,6 +281,7 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
errMsg: responseError.errMsg ?? responseError.errorMessage,
errno: responseError.errno ?? responseError.error,
};
transformResponse(responseError);
config.fail(responseError);
},
@ -293,7 +294,7 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
response.status = response.status ?? response.statusCode;
response.headers = response.headers ?? response.header;
origIgnore(response, [
orgIgnore(response, [
'statusCode',
'errMsg',
'errno',
@ -324,8 +325,7 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
options.fileType = fileType;
options.formData = formData;
origIgnore(options, ['params', 'data']);
orgIgnore(options, ['params', 'data']);
return upload(options);
}
@ -340,18 +340,16 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
response.data = {
filePath: response.filePath,
tempFilePath:
response.tempFilePath ||
response.tempFilePath ??
// response.apFilePath 为支付宝小程序基础库小于 2.7.23 的特有属性。
response.apFilePath,
};
origIgnore(response, ['tempFilePath', 'apFilePath', 'filePath']);
orgIgnore(response, ['tempFilePath', 'apFilePath', 'filePath']);
success(response);
};
origIgnore(options, ['params']);
orgIgnore(options, ['params']);
return download(options);
}

View File

@ -6,52 +6,50 @@ import { AxiosAdapterPlatform, createAdapter } from './createAdapter';
*/
export function getDefaultAdapter() {
const platform = revisePlatformApiNames(getPlatform());
if (!isPlatform(platform)) {
return;
if (isPlatform(platform)) {
return createAdapter(platform);
}
function getPlatform() {
const undef = 'undefined';
if (typeof wx !== undef) {
return wx;
} else if (typeof my !== undef) {
return my;
} else if (typeof swan !== undef) {
return swan;
} else if (typeof tt !== undef) {
return tt;
} else if (typeof qq !== undef) {
return qq;
} else if (typeof qh !== undef) {
return qh;
} else if (typeof ks !== undef) {
return ks;
} else if (typeof dd !== undef) {
return dd;
} else if (typeof jd !== undef) {
return jd;
}
}
function revisePlatformApiNames(platform?: AnyObject) {
return (
platform && {
request: platform.request ?? platform.httpRequest,
upload: platform.upload ?? platform.uploadFile,
download: platform.download ?? platform.downloadFile,
}
);
}
function isPlatform(value: any): value is AxiosAdapterPlatform {
return (
isPlainObject(value) &&
isFunction(value.request) &&
isFunction(value.upload) &&
isFunction(value.download)
);
}
return createAdapter(platform);
}
function getPlatform() {
const undef = 'undefined';
if (typeof wx !== undef) {
return wx;
} else if (typeof my !== undef) {
return my;
} else if (typeof swan !== undef) {
return swan;
} else if (typeof tt !== undef) {
return tt;
} else if (typeof qq !== undef) {
return qq;
} else if (typeof qh !== undef) {
return qh;
} else if (typeof ks !== undef) {
return ks;
} else if (typeof dd !== undef) {
return dd;
} else if (typeof jd !== undef) {
return jd;
}
}
function revisePlatformApiNames(platform?: AnyObject) {
if (platform) {
return {
request: platform.request ?? platform.httpRequest,
upload: platform.upload ?? platform.uploadFile,
download: platform.download ?? platform.downloadFile,
};
}
}
function isPlatform(value: any): value is AxiosAdapterPlatform {
return (
isPlainObject(value) &&
isFunction(value.request) &&
isFunction(value.upload) &&
isFunction(value.download)
);
}

View File

@ -44,14 +44,6 @@ export interface AxiosInstance extends AxiosRequest, Axios {
* @param config
*/
extend(config: AxiosRequestConfig): AxiosInstance;
/**
*
*
* @param config
*
* @deprecated 使 extend fork
*/
fork(config: AxiosRequestConfig): AxiosInstance;
}
export function createInstance(
@ -72,7 +64,6 @@ export function createInstance(
config.baseURL = combineURL(defaults.baseURL, config.baseURL);
return createInstance(mergeConfig(defaults, config), context);
};
instance.fork = instance.extend;
Object.assign(instance, context);
Object.setPrototypeOf(instance, Axios.prototype);

View File

@ -9,7 +9,7 @@ export function ignore<T extends AnyObject, K extends keyof T>(
...keys: K[]
): Omit<T, K> {
const res = { ...obj };
origIgnore(res, keys);
orgIgnore(res, keys);
return res;
}
@ -19,7 +19,7 @@ export function ignore<T extends AnyObject, K extends keyof T>(
* @param obj
* @param keys
*/
export function origIgnore(obj: AnyObject, keys: PropertyKey[]) {
export function orgIgnore(obj: AnyObject, keys: PropertyKey[]) {
for (const key of keys) {
delete obj[key as string | number];
}

View File

@ -27,7 +27,6 @@ describe('src/axios.ts', () => {
});
expect(instance.interceptors).toBeTypeOf('object');
expect(instance.getUri).toBeTypeOf('function');
expect(instance.fork).toBeTypeOf('function');
expect(instance.request).toBeTypeOf('function');
eachMethods((k) => {

View File

@ -19,7 +19,6 @@ describe('src/axios.ts', () => {
expect(axios.create).toBeTypeOf('function');
expect(axios.extend).toBeTypeOf('function');
expect(axios.use).toBeTypeOf('function');
expect(axios.fork).toBeTypeOf('function');
expect(axios.request).toBeTypeOf('function');
});

View File

@ -12,7 +12,6 @@ describe('src/core/createInstance.ts', () => {
expect(i.getUri).toBeTypeOf('function');
expect(i.create).toBeTypeOf('function');
expect(i.extend).toBeTypeOf('function');
expect(i.fork).toBeTypeOf('function');
expect(i.use).toBeTypeOf('function');
expect(i.request).toBeTypeOf('function');

View File

@ -1,5 +1,5 @@
import { describe, test, expect } from 'vitest';
import { ignore, origIgnore } from '@/helpers/ignore';
import { ignore, orgIgnore } from '@/helpers/ignore';
describe('src/helpers/ignore.ts', () => {
test('不应该改变传递的对象', () => {
@ -55,20 +55,20 @@ describe('src/helpers/ignore.ts', () => {
v3: [],
};
origIgnore(o, ['v1']);
orgIgnore(o, ['v1']);
expect(o).toEqual({
v2: {},
v3: [],
});
origIgnore(o, ['v2']);
orgIgnore(o, ['v2']);
expect(o).toEqual({
v3: [],
});
origIgnore(o, ['v3']);
orgIgnore(o, ['v3']);
expect(o).toEqual({});
});