refactor: 默认值的设置流程移到 request 里
parent
258954afc1
commit
1867273460
|
@ -91,7 +91,7 @@ import axios from 'axios-miniprogram';
|
||||||
|
|
||||||
// 适配器
|
// 适配器
|
||||||
axios.defaults.adapter = (config) => {
|
axios.defaults.adapter = (config) => {
|
||||||
// 可以先看看 config 都有哪些东西
|
// 可以先看看 config 上都有哪些属性
|
||||||
console.log(config);
|
console.log(config);
|
||||||
|
|
||||||
// 开始适配不同类型的请求
|
// 开始适配不同类型的请求
|
||||||
|
@ -122,13 +122,16 @@ axios.defaults.adapter = (config) => {
|
||||||
success: (response) => {
|
success: (response) => {
|
||||||
config.success({
|
config.success({
|
||||||
// 状态码
|
// 状态码
|
||||||
|
// 默认值:200
|
||||||
status: response.statusCode,
|
status: response.statusCode,
|
||||||
|
|
||||||
// 状态文本,选填,不传默认 'OK'
|
// 状态文本
|
||||||
|
// 默认值:'OK'
|
||||||
statusText: 'OK',
|
statusText: 'OK',
|
||||||
|
|
||||||
// 响应头
|
// 响应头
|
||||||
headers: response.header ?? {},
|
// 默认值:{}
|
||||||
|
headers: response.header,
|
||||||
|
|
||||||
// 响应数据
|
// 响应数据
|
||||||
data: response.data,
|
data: response.data,
|
||||||
|
@ -139,13 +142,16 @@ axios.defaults.adapter = (config) => {
|
||||||
},
|
},
|
||||||
fail: (error) => {
|
fail: (error) => {
|
||||||
config.fail({
|
config.fail({
|
||||||
// 状态码,选填,不传默认 400
|
// 状态码
|
||||||
|
// 默认值:400
|
||||||
status: 400,
|
status: 400,
|
||||||
|
|
||||||
// 状态文本,选填,不传默认 'Fail Adapter'
|
// 状态文本
|
||||||
statusText: 'Fail Adapter',
|
// 默认值:'Fail'
|
||||||
|
statusText: 'Fail',
|
||||||
|
|
||||||
// 响应头,选填,不传默认 {}
|
// 响应头
|
||||||
|
// 默认值:{}
|
||||||
headers: {},
|
headers: {},
|
||||||
|
|
||||||
// 响应数据
|
// 响应数据
|
||||||
|
@ -171,12 +177,15 @@ axios.defaults.adapter = (config) => {
|
||||||
success: (response) => {
|
success: (response) => {
|
||||||
config.success({
|
config.success({
|
||||||
// 状态码
|
// 状态码
|
||||||
|
// 默认值:200
|
||||||
status: response.statusCode,
|
status: response.statusCode,
|
||||||
|
|
||||||
// 状态文本,选填,不传默认 'OK'
|
// 状态文本
|
||||||
|
// 默认值:'OK'
|
||||||
statusText: 'OK',
|
statusText: 'OK',
|
||||||
|
|
||||||
// 响应头
|
// 响应头
|
||||||
|
// 默认值:{}
|
||||||
headers: response.header,
|
headers: response.header,
|
||||||
|
|
||||||
// 响应数据
|
// 响应数据
|
||||||
|
@ -185,13 +194,16 @@ axios.defaults.adapter = (config) => {
|
||||||
},
|
},
|
||||||
fail: (error) => {
|
fail: (error) => {
|
||||||
config.fail({
|
config.fail({
|
||||||
// 状态码,选填,不传默认 400
|
// 状态码
|
||||||
|
// 默认值:400
|
||||||
status: 400,
|
status: 400,
|
||||||
|
|
||||||
// 状态文本,选填,不传默认 'Fail Adapter'
|
// 状态文本
|
||||||
statusText: 'Fail Adapter',
|
// 默认值:'Fail'
|
||||||
|
statusText: 'Fail',
|
||||||
|
|
||||||
// 响应头,选填,不传默认 {}
|
// 响应头
|
||||||
|
// 默认值:{}
|
||||||
headers: {},
|
headers: {},
|
||||||
|
|
||||||
// 响应数据
|
// 响应数据
|
||||||
|
@ -210,13 +222,16 @@ axios.defaults.adapter = (config) => {
|
||||||
success: (response) => {
|
success: (response) => {
|
||||||
config.success({
|
config.success({
|
||||||
// 状态码
|
// 状态码
|
||||||
|
// 默认值:200
|
||||||
status: response.statusCode,
|
status: response.statusCode,
|
||||||
|
|
||||||
// 状态文本,选填,不传默认 'OK'
|
// 状态文本
|
||||||
|
// 默认值:'OK'
|
||||||
statusText: 'OK',
|
statusText: 'OK',
|
||||||
|
|
||||||
// 响应头
|
// 响应头
|
||||||
headers: response.header ?? {},
|
// 默认值:{}
|
||||||
|
headers: response.header,
|
||||||
|
|
||||||
// 响应数据
|
// 响应数据
|
||||||
data: {
|
data: {
|
||||||
|
@ -227,13 +242,16 @@ axios.defaults.adapter = (config) => {
|
||||||
},
|
},
|
||||||
fail: (error) => {
|
fail: (error) => {
|
||||||
config.fail({
|
config.fail({
|
||||||
// 状态码,选填,不传默认 400
|
// 状态码
|
||||||
|
// 默认值:400
|
||||||
status: 400,
|
status: 400,
|
||||||
|
|
||||||
// 状态文本,选填,不传默认 'Fail Adapter'
|
// 状态文本
|
||||||
statusText: 'Fail Adapter',
|
// 默认值:'Fail'
|
||||||
|
statusText: 'Fail',
|
||||||
|
|
||||||
// 响应头,选填,不传默认 {}
|
// 响应头
|
||||||
|
// 默认值:{}
|
||||||
headers: {},
|
headers: {},
|
||||||
|
|
||||||
// 响应数据
|
// 响应数据
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
"main": "dist/axios-miniprogram.cjs.js",
|
"main": "dist/axios-miniprogram.cjs.js",
|
||||||
"module": "dist/axios-miniprogram.esm.js",
|
"module": "dist/axios-miniprogram.esm.js",
|
||||||
"types": "dist/axios-miniprogram.d.ts",
|
"types": "dist/axios-miniprogram.d.ts",
|
||||||
"type": "module",
|
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
|
@ -25,6 +24,7 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://axios-miniprogram.com",
|
"homepage": "https://axios-miniprogram.com",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"cz": "simple-git-hooks && czg",
|
"cz": "simple-git-hooks && czg",
|
||||||
"build": "esno scripts/build.ts",
|
"build": "esno scripts/build.ts",
|
||||||
|
|
168
src/adapter.ts
168
src/adapter.ts
|
@ -1,9 +1,4 @@
|
||||||
import {
|
import { isFunction, isPlainObject } from './helpers/isTypes';
|
||||||
isFunction,
|
|
||||||
isPlainObject,
|
|
||||||
isString,
|
|
||||||
isUndefined,
|
|
||||||
} from './helpers/isTypes';
|
|
||||||
import { assert } from './helpers/error';
|
import { assert } from './helpers/error';
|
||||||
import {
|
import {
|
||||||
AxiosProgressCallback,
|
AxiosProgressCallback,
|
||||||
|
@ -138,8 +133,17 @@ export interface AxiosAdapterRequestConfig extends AnyObject {
|
||||||
* 请求函数基本选项
|
* 请求函数基本选项
|
||||||
*/
|
*/
|
||||||
export interface AxiosAdapterBaseOptions extends AxiosAdapterRequestConfig {
|
export interface AxiosAdapterBaseOptions extends AxiosAdapterRequestConfig {
|
||||||
|
/**
|
||||||
|
* 请求头,同 headers
|
||||||
|
*/
|
||||||
header?: AxiosRequestHeaders;
|
header?: AxiosRequestHeaders;
|
||||||
|
/**
|
||||||
|
* 成功的回调
|
||||||
|
*/
|
||||||
success(response: AxiosAdapterResponse): void;
|
success(response: AxiosAdapterResponse): void;
|
||||||
|
/**
|
||||||
|
* 失败的回调
|
||||||
|
*/
|
||||||
fail(error: AxiosAdapterResponseError): void;
|
fail(error: AxiosAdapterResponseError): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +156,9 @@ export type AxiosAdapterRequestOptions = AxiosAdapterBaseOptions;
|
||||||
* 下载函数选项
|
* 下载函数选项
|
||||||
*/
|
*/
|
||||||
export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions {
|
export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions {
|
||||||
|
/**
|
||||||
|
* 文件下载后存储的路径
|
||||||
|
*/
|
||||||
filePath?: string;
|
filePath?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +168,17 @@ export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions {
|
||||||
export interface AxiosAdapterUploadOptions
|
export interface AxiosAdapterUploadOptions
|
||||||
extends AxiosAdapterBaseOptions,
|
extends AxiosAdapterBaseOptions,
|
||||||
AxiosRequestFormData {
|
AxiosRequestFormData {
|
||||||
|
/**
|
||||||
|
* [钉钉小程序用 fileName 代替 name](https://open.dingtalk.com/document/orgapp/dd-upload-objects#title-ngk-rr1-eow)
|
||||||
|
*/
|
||||||
fileName: string;
|
fileName: string;
|
||||||
|
/**
|
||||||
|
* 钉钉小程序|支付宝小程序特有参数
|
||||||
|
*/
|
||||||
|
fileType?: 'image' | 'video' | 'audie';
|
||||||
|
/**
|
||||||
|
* 额外的数据
|
||||||
|
*/
|
||||||
formData?: AnyObject;
|
formData?: AnyObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,15 +307,42 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
|
||||||
function adapter(
|
function adapter(
|
||||||
config: AxiosAdapterRequestConfig,
|
config: AxiosAdapterRequestConfig,
|
||||||
): AxiosAdapterPlatformTask {
|
): AxiosAdapterPlatformTask {
|
||||||
const baseOptions = transformOptions(config);
|
const options = transformOptions(config);
|
||||||
|
|
||||||
switch (config.type) {
|
switch (config.type) {
|
||||||
case 'request':
|
case 'request':
|
||||||
return processRequest(platform.request, baseOptions);
|
return processRequest(platform.request, options);
|
||||||
case 'download':
|
case 'download':
|
||||||
return processDownload(platform.download, baseOptions);
|
return processDownload(platform.download, options);
|
||||||
case 'upload':
|
case 'upload':
|
||||||
return processUpload(platform.upload, baseOptions);
|
return processUpload(platform.upload, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformOptions(
|
||||||
|
config: AxiosAdapterRequestConfig,
|
||||||
|
): AxiosAdapterBaseOptions {
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
success(response) {
|
||||||
|
transformResponse(response);
|
||||||
|
config.success(response);
|
||||||
|
},
|
||||||
|
fail(responseError) {
|
||||||
|
responseError.data = {
|
||||||
|
errMsg: responseError.errMsg,
|
||||||
|
errno: responseError.errno,
|
||||||
|
};
|
||||||
|
transformResponse(responseError);
|
||||||
|
config.fail(responseError);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function transformResponse(
|
||||||
|
response: AxiosAdapterResponse | AxiosAdapterResponseError,
|
||||||
|
) {
|
||||||
|
response.status = response.status ?? response.statusCode;
|
||||||
|
response.headers = response.headers ?? response.header;
|
||||||
|
clean(response, ['statusCode', 'errMsg', 'errno', 'header']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,22 +357,14 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
|
||||||
upload: AxiosAdapterUpload,
|
upload: AxiosAdapterUpload,
|
||||||
baseOptions: AxiosAdapterBaseOptions,
|
baseOptions: AxiosAdapterBaseOptions,
|
||||||
): AxiosAdapterPlatformTask {
|
): AxiosAdapterPlatformTask {
|
||||||
const { name, filePath, fileType, ...formData } =
|
const options = baseOptions as AxiosAdapterUploadOptions;
|
||||||
baseOptions.data as AxiosRequestFormData;
|
const { name, filePath, fileType, ...formData } = options.data as AnyObject;
|
||||||
const options = {
|
|
||||||
...baseOptions,
|
options.name = name;
|
||||||
name,
|
options.fileName = name;
|
||||||
/**
|
options.filePath = filePath;
|
||||||
* [钉钉小程序用 fileName 代替 name](https://open.dingtalk.com/document/orgapp/dd-upload-objects#title-ngk-rr1-eow)
|
options.fileType = fileType;
|
||||||
*/
|
options.formData = formData;
|
||||||
fileName: name,
|
|
||||||
filePath,
|
|
||||||
/**
|
|
||||||
* 钉钉小程序|支付宝小程序特有参数
|
|
||||||
*/
|
|
||||||
fileType,
|
|
||||||
formData,
|
|
||||||
};
|
|
||||||
|
|
||||||
return upload(options);
|
return upload(options);
|
||||||
}
|
}
|
||||||
|
@ -337,74 +373,28 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
|
||||||
download: AxiosAdapterDownload,
|
download: AxiosAdapterDownload,
|
||||||
baseOptions: AxiosAdapterBaseOptions,
|
baseOptions: AxiosAdapterBaseOptions,
|
||||||
): AxiosAdapterPlatformTask {
|
): AxiosAdapterPlatformTask {
|
||||||
const options: AxiosAdapterDownloadOptions = {
|
const options = baseOptions as AxiosAdapterDownloadOptions;
|
||||||
...baseOptions,
|
const { params, success } = options;
|
||||||
filePath: baseOptions.params?.filePath,
|
|
||||||
success(response): void {
|
options.filePath = params?.filePath;
|
||||||
injectDownloadData(response);
|
options.success = (response) => {
|
||||||
baseOptions.success(response);
|
response.data = {
|
||||||
},
|
filePath: response.filePath,
|
||||||
|
tempFilePath:
|
||||||
|
response.tempFilePath ||
|
||||||
|
// response.apFilePath 为支付宝小程序基础库小于 2.7.23 的特有属性。
|
||||||
|
response.apFilePath,
|
||||||
|
};
|
||||||
|
clean(response, ['tempFilePath', 'apFilePath', 'filePath']);
|
||||||
|
success(response);
|
||||||
};
|
};
|
||||||
|
|
||||||
return download(options);
|
return download(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
function transformResponse(response: AnyObject): void {
|
function clean(obj: AnyObject, keys: string[]) {
|
||||||
response.status = response.status ?? response.statusCode;
|
|
||||||
response.statusText = 'OK';
|
|
||||||
|
|
||||||
if (isUndefined(response.status)) {
|
|
||||||
response.status = 400;
|
|
||||||
response.statusText = 'Fail Adapter';
|
|
||||||
}
|
|
||||||
|
|
||||||
response.headers = response.headers ?? response.header ?? {};
|
|
||||||
|
|
||||||
if (isUndefined(response.data) && isString(response.errMsg)) {
|
|
||||||
response.data = {
|
|
||||||
errMsg: response.errMsg,
|
|
||||||
errno: response.errno,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanResponse(response, ['statusCode', 'errMsg', 'errno', 'header']);
|
|
||||||
}
|
|
||||||
|
|
||||||
function transformOptions(
|
|
||||||
config: AxiosAdapterRequestConfig,
|
|
||||||
): AxiosAdapterBaseOptions {
|
|
||||||
return {
|
|
||||||
...config,
|
|
||||||
header: config.headers,
|
|
||||||
success(response): void {
|
|
||||||
transformResponse(response);
|
|
||||||
config.success(response);
|
|
||||||
},
|
|
||||||
fail(error: AxiosAdapterResponseError): void {
|
|
||||||
transformResponse(error);
|
|
||||||
config.fail(error);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function injectDownloadData(response: AnyObject): void {
|
|
||||||
response.data = {
|
|
||||||
filePath: response.filePath,
|
|
||||||
tempFilePath:
|
|
||||||
response.tempFilePath ||
|
|
||||||
// response.apFilePath 为支付宝小程序基础库小于 2.7.23 的特有属性。
|
|
||||||
response.apFilePath,
|
|
||||||
};
|
|
||||||
|
|
||||||
cleanResponse(response, ['tempFilePath', 'apFilePath', 'filePath']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清理 response 上多余的 key
|
|
||||||
*/
|
|
||||||
function cleanResponse(response: AnyObject, keys: string[]) {
|
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
delete response[key];
|
delete obj[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ export type AxiosRequestData =
|
||||||
/**
|
/**
|
||||||
* 响应数据
|
* 响应数据
|
||||||
*/
|
*/
|
||||||
export type AxiosResponseData = undefined | number | AxiosAdapterResponseData;
|
export type AxiosResponseData = number | AxiosAdapterResponseData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监听进度回调事件对象
|
* 监听进度回调事件对象
|
||||||
|
@ -259,7 +259,7 @@ export interface AxiosResponseError extends AnyObject {
|
||||||
/**
|
/**
|
||||||
* 错误数据
|
* 错误数据
|
||||||
*/
|
*/
|
||||||
data?: AnyObject;
|
data: AnyObject;
|
||||||
/**
|
/**
|
||||||
* 失败的请求,指没能够成功响应的请求
|
* 失败的请求,指没能够成功响应的请求
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -56,10 +56,11 @@ export function request(config: AxiosRequestConfig) {
|
||||||
response.config = config;
|
response.config = config;
|
||||||
response.request = adapterTask;
|
response.request = adapterTask;
|
||||||
|
|
||||||
if (config.validateStatus?.(response.status) ?? true) {
|
const { validateStatus } = config;
|
||||||
|
if (!isFunction(validateStatus) || validateStatus(response.status)) {
|
||||||
resolve(response);
|
resolve(response);
|
||||||
} else {
|
} else {
|
||||||
catchError('validate status fail', response);
|
catchError('validate status error', response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ export function request(config: AxiosRequestConfig) {
|
||||||
const responseError = baseResponseError as AxiosResponseError;
|
const responseError = baseResponseError as AxiosResponseError;
|
||||||
responseError.isFail = true;
|
responseError.isFail = true;
|
||||||
responseError.status = responseError.status ?? 400;
|
responseError.status = responseError.status ?? 400;
|
||||||
responseError.statusText = responseError.statusText ?? 'Fail Adapter';
|
responseError.statusText = responseError.statusText ?? 'Fail';
|
||||||
responseError.headers = responseError.headers ?? {};
|
responseError.headers = responseError.headers ?? {};
|
||||||
responseError.config = config;
|
responseError.config = config;
|
||||||
responseError.request = adapterTask;
|
responseError.request = adapterTask;
|
||||||
|
|
|
@ -81,9 +81,6 @@ describe('src/adapter.ts', () => {
|
||||||
expect(p.request.mock.calls[0][0]).toMatchInlineSnapshot(`
|
expect(p.request.mock.calls[0][0]).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"fail": [Function],
|
"fail": [Function],
|
||||||
"header": {
|
|
||||||
"Accept": "application/json, text/plain, */*",
|
|
||||||
},
|
|
||||||
"headers": {
|
"headers": {
|
||||||
"Accept": "application/json, text/plain, */*",
|
"Accept": "application/json, text/plain, */*",
|
||||||
},
|
},
|
||||||
|
@ -112,9 +109,6 @@ describe('src/adapter.ts', () => {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"user": "test",
|
"user": "test",
|
||||||
},
|
},
|
||||||
"header": {
|
|
||||||
"Accept": "application/json, text/plain, */*",
|
|
||||||
},
|
|
||||||
"headers": {
|
"headers": {
|
||||||
"Accept": "application/json, text/plain, */*",
|
"Accept": "application/json, text/plain, */*",
|
||||||
},
|
},
|
||||||
|
@ -132,9 +126,6 @@ describe('src/adapter.ts', () => {
|
||||||
{
|
{
|
||||||
"fail": [Function],
|
"fail": [Function],
|
||||||
"filePath": "/path/file",
|
"filePath": "/path/file",
|
||||||
"header": {
|
|
||||||
"Accept": "application/json, text/plain, */*",
|
|
||||||
},
|
|
||||||
"headers": {
|
"headers": {
|
||||||
"Accept": "application/json, text/plain, */*",
|
"Accept": "application/json, text/plain, */*",
|
||||||
},
|
},
|
||||||
|
@ -271,9 +262,12 @@ describe('src/adapter.ts', () => {
|
||||||
fail: (response: any) => {
|
fail: (response: any) => {
|
||||||
expect(response).toMatchInlineSnapshot(`
|
expect(response).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"headers": {},
|
"data": {
|
||||||
"status": 400,
|
"errMsg": undefined,
|
||||||
"statusText": "Fail Adapter",
|
"errno": undefined,
|
||||||
|
},
|
||||||
|
"headers": undefined,
|
||||||
|
"status": undefined,
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
},
|
},
|
||||||
|
@ -284,11 +278,11 @@ describe('src/adapter.ts', () => {
|
||||||
expect(response).toMatchInlineSnapshot(`
|
expect(response).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"result": null,
|
"errMsg": undefined,
|
||||||
|
"errno": undefined,
|
||||||
},
|
},
|
||||||
"headers": {},
|
"headers": undefined,
|
||||||
"status": 500,
|
"status": 500,
|
||||||
"statusText": "OK",
|
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
},
|
},
|
||||||
|
@ -302,9 +296,8 @@ describe('src/adapter.ts', () => {
|
||||||
"errMsg": "request:fail",
|
"errMsg": "request:fail",
|
||||||
"errno": 1000,
|
"errno": 1000,
|
||||||
},
|
},
|
||||||
"headers": {},
|
"headers": undefined,
|
||||||
"status": 400,
|
"status": undefined,
|
||||||
"statusText": "Fail Adapter",
|
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue