pull/1/head
954270063@qq.com 2020-04-20 10:34:16 +08:00
parent e52a960b5b
commit b505dade41
19 changed files with 212 additions and 95 deletions

View File

@ -311,7 +311,7 @@ instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlenco
##### 配置优先顺序
发送请求时,会使用默认配置`defaults`和自定义配置`config`合并出请求配置`requestConfig`,然后用合并出的请求配置`requestConfig`去发送请求,多数情况下,后者优先级要高于前者,具体合并策略可以参考 [mergeConfig.ts](https://github.com/early-autumn/axios-miniprogram/blob/master/src/helpers/mergeConfig.ts) 的实现。
发送请求时,会使用默认配置`defaults`和自定义配置`config`合并出请求配置`requestConfig`,然后用合并出的请求配置`requestConfig`去发送请求,多数情况下,后者优先级要高于前者,具体合并策略可以参考 [mergeConfig.ts](https://github.com/early-autumn/axios-miniprogram/blob/master/src/core/mergeConfig.ts) 的实现。
## 响应体`response`

View File

@ -1,6 +1,6 @@
{
"name": "axios-miniprogram",
"version": "1.0.6",
"version": "1.0.7",
"description": "基于 Promise 的 HTTP 请求库,适用于各大小程序平台。",
"main": "package/index.js",
"miniprogram": "package",

View File

@ -2,14 +2,14 @@
* @Author: early-autumn
* @Date: 2020-04-15 12:45:18
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-19 01:40:54
* @LastEditTime: 2020-04-20 09:27:03
*/
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 mergeConfig from './helpers/mergeConfig';
import defaults from './helpers/defaults';
import defaults from './defaults';
/**
* Axios

View File

@ -2,11 +2,11 @@
* @Author: early-autumn
* @Date: 2020-04-13 18:00:27
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-19 22:12:04
* @LastEditTime: 2020-04-20 09:12:46
*/
import { Method, Params, Data, Interceptors, AxiosRequestConfig, AxiosResponse, Axios } from '../types';
import buildURL from '../helpers/buildURL';
import mergeConfig from '../helpers/mergeConfig';
import mergeConfig from './mergeConfig';
import InterceptorManager from './InterceptorManager';
import dispatchRequest from './dispatchRequest';

View File

@ -2,10 +2,10 @@
* @Author: early-autumn
* @Date: 2020-04-15 22:48:25
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-18 22:58:05
* @LastEditTime: 2020-04-20 10:32:06
*/
import { AxiosRequestConfig } from '../types';
import { isPlainObject, deepMerge } from './utils';
import { AnyObject, AxiosRequestConfig } from '../types';
import { isPlainObject, deepMerge } from '../helpers/utils';
/**
* config2
@ -23,7 +23,7 @@ function onlyFromConfig2(keys: ['url', 'data'], config: AxiosRequestConfig, conf
}
/**
* config2
* config2 , config2 config1
*
* @param keys
* @param config
@ -77,11 +77,11 @@ function deepMergeConfig(
) {
keys.forEach((key) => {
if (isPlainObject(config2[key])) {
config[key] = deepMerge(config1[key] as any, config2[key] as any);
config[key] = deepMerge(config1[key] ?? {}, config2[key] as AnyObject);
} else if (config2[key] !== undefined) {
config[key] = config2[key];
} else if (isPlainObject(config1[key])) {
config[key] = deepMerge(config1[key] as any);
config[key] = deepMerge(config1[key] as AnyObject);
} else if (config1[key] !== undefined) {
config[key] = config1[key];
}
@ -94,7 +94,10 @@ function deepMergeConfig(
* @param config1 Axios 1
* @param config2 Axios 2
*/
export default function mergeConfig(config1: AxiosRequestConfig, config2: AxiosRequestConfig): AxiosRequestConfig {
export default function mergeConfig(
config1: AxiosRequestConfig = {},
config2: AxiosRequestConfig = {}
): AxiosRequestConfig {
const config: AxiosRequestConfig = {};
onlyFromConfig2(['url', 'data'], config, config2);

View File

@ -2,10 +2,12 @@
* @Author: early-autumn
* @Date: 2020-04-17 15:05:43
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-20 01:08:23
* @LastEditTime: 2020-04-20 09:19:49
*/
import { AdapterMethod, AxiosRequestConfig, RequestConfig } from '../types';
import { isAbsoluteURL, combineURL, pick } from '../helpers/utils';
import { pick } from '../helpers/utils';
import isAbsoluteURL from '../helpers/isAbsoluteURL';
import combineURL from '../helpers/combineURL';
import buildURL from '../helpers/buildURL';
type PickKeys = 'dataType' | 'responseType' | 'timeout' | 'enableHttp2' | 'enableQuic' | 'enableCache' | 'sslVerify';
@ -41,7 +43,7 @@ function transformURL(config: AxiosRequestConfig): string {
export default function transformRequest(config: AxiosRequestConfig): RequestConfig {
const url = transformURL(config);
const method = methodUppercase(config);
const pickConfig = pick<AxiosRequestConfig, PickKeys>(
const pickRequest = pick<AxiosRequestConfig, PickKeys>(
config,
'dataType',
'responseType',
@ -56,6 +58,6 @@ export default function transformRequest(config: AxiosRequestConfig): RequestCon
url,
method,
header: config.headers,
...pickConfig,
...pickRequest,
} as RequestConfig;
}

View File

@ -2,7 +2,7 @@
* @Author: early-autumn
* @Date: 2020-04-17 14:09:16
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-20 01:06:39
* @LastEditTime: 2020-04-20 09:05:01
*/
import { AxiosRequestConfig, AxiosResponse, Response } from '../types';
import { pick } from '../helpers/utils';
@ -17,8 +17,8 @@ import { pick } from '../helpers/utils';
* @param config Axios
*/
export default function transformResponse(response: Response, config: AxiosRequestConfig): AxiosResponse {
const status = response.status ?? response.statusCode;
const headers = response.headers ?? response.header;
const status = response.statusCode ?? response.status ?? 400;
const headers = response.header ?? response.headers ?? {};
const statusText = status === 200 ? 'OK' : status === 400 ? 'Bad Adapter' : '';
const pickResponse = pick<Response, 'data' | 'cookies' | 'profile'>(response, 'data', 'cookies', 'profile');

View File

@ -2,10 +2,10 @@
* @Author: early-autumn
* @Date: 2020-04-15 22:09:38
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-20 01:14:00
* @LastEditTime: 2020-04-20 09:26:14
*/
import { AxiosRequestConfig } from '../types';
import adaptive from '../adaptive';
import { AxiosRequestConfig } from './types';
import adaptive from './adaptive';
const defaults: AxiosRequestConfig = {
adapter: adaptive(),

View File

@ -2,26 +2,10 @@
* @Author: early-autumn
* @Date: 2020-04-13 21:45:45
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-19 23:30:42
* @LastEditTime: 2020-04-20 09:35:48
*/
import { AnyObject, Params } from '../types';
import { isPlainObject, isDate } from './utils';
/**
*
*
* @param str
*/
function encode(str: string): string {
return encodeURIComponent(str)
.replace(/%40/g, '@')
.replace(/%3A/gi, ':')
.replace(/%24/g, '$')
.replace(/%2C/gi, ',')
.replace(/%20/g, '+')
.replace(/%5B/gi, '[')
.replace(/%5D/gi, ']');
}
import { encode, isPlainObject, isDate } from './utils';
/**
*

15
src/helpers/combineURL.ts Normal file
View File

@ -0,0 +1,15 @@
/*
* @Author: early-autumn
* @Date: 2020-04-20 09:16:47
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-20 09:19:23
*/
/**
* 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(/^\/*/, '')}`;
}

View File

@ -0,0 +1,17 @@
/*
* @Author: early-autumn
* @Date: 2020-04-20 09:17:40
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-20 09:19:11
*/
/**
* URL
*
* xxx:// 或者 "//" 开头, 视为绝对地址
*
* @param url URL
*/
export default function isAbsoluteURL(url: string): boolean {
return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
}

View File

@ -2,12 +2,28 @@
* @Author: early-autumn
* @Date: 2020-04-13 21:55:40
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-19 16:08:40
* @LastEditTime: 2020-04-20 10:24:00
*/
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, ']');
}
/**
*
*
@ -26,26 +42,6 @@ export function isPlainObject(obj: any): obj is object {
return _toString.call(obj) === '[object Object]';
}
/**
* URL
*
* xxx:// 或者 "//" 开头, 视为绝对地址
*
* @param url URL
*/
export function isAbsoluteURL(url: string): boolean {
return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
}
/**
* baseURL url URL
*
* combineURL('1/2///','////3/4') => '1/2/3/4'
*/
export function combineURL(baseURL: string, url: string): string {
return `${baseURL.replace(/\/*$/, '')}/${url.replace(/^\/*/, '')}`;
}
/**
*
*
@ -73,9 +69,6 @@ export function deepMerge(...objs: Record<string, any>[]): Record<string, any> {
}
objs.forEach((obj: Record<string, any>): void => {
if (obj === undefined) {
return;
}
Object.entries(obj).forEach(([key, value]) => assignValue(key, value));
});
@ -91,7 +84,9 @@ export function deepMerge(...objs: Record<string, any>[]): Record<string, any> {
export function pick<T extends AnyObject, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> {
const _pick: Partial<T> = {};
keys.forEach((key: K) => (_pick[key] = obj[key]));
keys.forEach(function pickKey(key: K) {
_pick[key] = obj[key];
});
return _pick as Pick<T, K>;
}
@ -105,7 +100,9 @@ export function pick<T extends AnyObject, K extends keyof T>(obj: T, ...keys: K[
export function omit<T extends AnyObject, K extends keyof T>(obj: T, ...keys: K[]): Omit<T, K> {
const _omit = { ...obj };
keys.forEach((key: K) => delete _omit[key]);
keys.forEach(function omitKey(key: K) {
delete _omit[key];
});
return _omit;
}

View File

@ -2,11 +2,11 @@
* @Author: early-autumn
* @Date: 2020-04-19 22:30:24
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-19 22:45:00
* @LastEditTime: 2020-04-20 09:49:35
*/
/**
*
*
*
* @param message
*/

View File

@ -2,7 +2,7 @@
* @Author: early-autumn
* @Date: 2020-04-13 15:23:53
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-19 23:30:07
* @LastEditTime: 2020-04-20 10:32:48
*/
/**
*
@ -161,17 +161,17 @@ export interface Response {
/**
*
*/
statusCode: number;
/**
* Headers
*/
header: AnyObject;
statusCode?: number;
/**
*
*/
status: number;
status?: number;
/**
* Headers
*/
header?: AnyObject;
/**
* Headers

View File

@ -1,14 +0,0 @@
/*
* @Author: early-autumn
* @Date: 2020-04-19 14:43:15
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-20 00:51:13
*/
import flattenHeaders from '../../src/core/flattenHeaders';
describe('测试 src/helpers/flattenHeaders.ts', () => {
it('测试 容错', () => {
expect(flattenHeaders({})).toEqual({});
// 'Content-Type': 'application/json; charset=utf-8',
});
});

View File

@ -2,11 +2,11 @@
* @Author: early-autumn
* @Date: 2020-04-19 14:34:13
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-19 23:16:55
* @LastEditTime: 2020-04-20 09:58:22
*/
import buildURL from '../../src/helpers/buildURL';
describe('测试 /helpers/buildURL.ts', () => {
describe('测试 src/helpers/buildURL.ts', () => {
it('url', () => {
expect(buildURL('/test')).toBe('/test');
expect(buildURL('/test?id=1')).toBe('/test?id=1');
@ -46,7 +46,43 @@ describe('测试 /helpers/buildURL.ts', () => {
).toBe('/test?id=1&paramsSerializer=ok');
});
it('delete hash', () => {
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: undefined,
NaN: NaN,
})
).toBe('/test');
});
});

View File

@ -0,0 +1,14 @@
/*
* @Author: early-autumn
* @Date: 2020-04-20 09:42:17
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-20 09:58:41
*/
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');
});
});

View File

@ -0,0 +1,16 @@
/*
* @Author: early-autumn
* @Date: 2020-04-20 09:42:17
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-20 10:27:07
*/
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);
});
});

47
test/helper/utils.test.ts Normal file
View File

@ -0,0 +1,47 @@
/*
* @Author: early-autumn
* @Date: 2020-04-20 10:02:56
* @LastEditors: early-autumn
* @LastEditTime: 2020-04-20 10:23:45
*/
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 });
});
});