Skip to content

Commit 4cc0c37

Browse files
committed
feat(api): 支持自定义response映射关系
1 parent 2ab680c commit 4cc0c37

File tree

4 files changed

+129
-72
lines changed

4 files changed

+129
-72
lines changed

src/actions/api.js

Lines changed: 57 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import ams from '../ams';
2-
import { getQueryString, getType, isFn } from '../utils';
2+
import { getQueryString, getType, isFn, responseHandler } from '../utils';
33
import { httpRequestTypeExcludeGet } from '../ams/request';
44

55
/**
@@ -112,19 +112,14 @@ export const read = ams.createApiAction({
112112
};
113113
},
114114
success(res) {
115-
const successCode = this.getConfig('resource.api.read.successCode') || this.getConfig('resource.api.successCode');
116-
if (res.data.code === successCode) {
117-
const config = this.resource.api.read;
118-
if (typeof config === 'object' && typeof config.transform === 'function') {
119-
this.setBlockData(config.transform(res.data.data));
120-
} else if (typeof config === 'object' && typeof config.responseDataParse === 'function') {
121-
this.setBlockData(config.responseDataParse(res.data));
122-
} else {
123-
this.setBlockData(res.data.data);
124-
}
115+
const { message, code, isSuccess, data } = responseHandler.call(this, res, 'read');
116+
if (isSuccess) {
117+
const { transform, responseDataParse } = this.resource.api.read || {};
118+
const handler = transform || responseDataParse || (data => data);
119+
this.setBlockData(handler(data));
125120
} else {
126-
this.$message.error(`${res.data.msg}(${res.data.code})`);
127-
throw '@read:' + res.data.code;
121+
this.$message.error(`${message}(${code})`);
122+
throw '@read:' + code;
128123
}
129124
return res;
130125
}
@@ -160,16 +155,14 @@ export const update = ams.createApiAction({
160155
};
161156
},
162157
success(res) {
163-
// 默认successCode
164-
const successCode = this.getConfig('resource.api.update.successCode') || this.getConfig('resource.api.successCode');
165-
if (res.data.code === successCode) {
158+
const { message, code, isSuccess } = responseHandler.call(this, res, 'update');
159+
if (isSuccess) {
166160
this.$message.success('更新成功');
167-
if (typeof this.on['update-success'] === 'function') {
168-
this.on['update-success'](res.data);
169-
}
161+
const onSuccess = this.on['update-success'];
162+
if (isFn(onSuccess)) onSuccess(res.data);
170163
} else {
171-
this.$message.error(`${res.data.msg}(${res.data.code})`);
172-
throw '@update:' + res.data.code;
164+
this.$message.error(`${message}(${code})`);
165+
throw '@update:' + code;
173166
}
174167
return res;
175168
}
@@ -206,16 +199,14 @@ export const deleteAction = ams.createApiAction({
206199
};
207200
},
208201
success(res) {
209-
// 默认successCode
210-
const successCode = this.getConfig('resource.api.delete.successCode') || this.getConfig('resource.api.successCode');
211-
if (res.data.code === successCode) {
202+
const { message, code, isSuccess } = responseHandler.call(this, res, 'delete');
203+
if (isSuccess) {
212204
this.$message.success('删除成功');
213-
if (typeof this.on['delete-success'] === 'function') {
214-
this.on['delete-success'](res.data);
215-
}
205+
const onSuccess = this.on['delete-success'];
206+
if (isFn(onSuccess)) onSuccess(res.data);
216207
} else {
217-
this.$message.error(`${res.data.msg}(${res.data.code})`);
218-
throw '@delete:' + res.data.code;
208+
this.$message.error(`${message}(${code})`);
209+
throw '@delete:' + code;
219210
}
220211
return res;
221212
}
@@ -245,21 +236,21 @@ export const create = ams.createApiAction({
245236
};
246237
},
247238
success(res) {
248-
// 默认successCode
249-
const successCode = this.getConfig('resource.api.create.successCode') || this.getConfig('resource.api.successCode');
250-
if (res.data.code === successCode) {
239+
const { message, code, isSuccess } = responseHandler.call(this, res, 'create');
240+
if (isSuccess) {
251241
this.$message.success('创建成功');
252-
if (typeof this.on['create-success'] === 'function') {
253-
this.on['create-success'](res.data);
254-
}
242+
const onSuccess = this.on['create-success'];
243+
if (isFn(onSuccess)) onSuccess(res.data);
255244
} else {
256-
this.$message.error(`${res.data.msg}(${res.data.code})`);
257-
throw '@create code:' + res.data.code;
245+
this.$message.error(`${message}(${code})`);
246+
throw '@create code:' + code;
258247
}
259248
return res;
260249
}
261250
});
262251

252+
// https://github.com/vipshop/ams/blob/5c8e0112c3b8e42c4bed9ff658767bbdbcf9bbd4/src/ams/request.js#L162
253+
// createApiAction -> src/ams/request.js
263254
export const list = ams.createApiAction({
264255
getOptions(params) {
265256
// 使用传入页数,如搜索使用 @list:1 将页数重置为1
@@ -336,37 +327,45 @@ export const list = ams.createApiAction({
336327
params: arg
337328
};
338329
},
330+
/**
331+
*
332+
* @param {*} res { status: statusCode, data: JSON.parse(xhr.responseText) }
333+
*/
339334
success(res) {
340-
// 默认successCode
341-
const successCode = this.getConfig('resource.api.list.successCode') || this.getConfig('resource.api.successCode');
342-
if (
343-
res.data.code === successCode &&
344-
res.data.data
345-
) {
346-
const config = this.resource.api.list;
347-
this.data.total = res.data.data.total;
335+
// whenSuccess = res => res[codePath] === expectedCode
336+
const { message, code, isSuccess, data, getter } = responseHandler.call(this, res, 'list');
337+
if (isSuccess) {
338+
const total = data[getter.totalPath];
339+
const list = data[getter.listPath];
340+
this.data.list = list;
341+
this.data.total = total;
348342

349-
if (typeof config === 'object' && typeof config.transform === 'function') {
350-
this.data.list = config.transform(res.data.data.list) || [];
351-
} else if (typeof config === 'object' && typeof config.responseDataParse === 'function') {
352-
const convertResponseDataParse = config.responseDataParse(res.data);
353-
if (getType(convertResponseDataParse) !== 'object') {
343+
const { transform, responseDataParse } = this.resource.api.list || {};
344+
if (isFn(transform)) {
345+
this.data.list = transform(data);
346+
347+
} else if (isFn(responseDataParse)) {
348+
const parsedData = responseDataParse(data);
349+
if (getType(parsedData) !== 'object') {
354350
console.error('responseDataParse中需要返回object类型,如{ list: [] }');
355351
this.data.list = [];
356352
} else {
357-
this.data = { ...this.data, ...config.responseDataParse(res.data) };
353+
this.data = {
354+
...this.data,
355+
...responseDataParse(data)
356+
};
358357
}
359-
} else {
360-
this.data.list = res.data.data.list || [];
361-
}
362-
if (typeof this.on['list-success'] === 'function') {
363-
this.on['list-success'](res.data);
364358
}
359+
const onSuccess = this.on['list-success'];
360+
if (isFn(onSuccess)) onSuccess(data);
365361
} else {
366-
this.$message.error(`${res.data.msg}(${res.data.code})`);
367-
throw '@list:' + res.data.code;
362+
this.$message.error(`${message}(${code})`);
363+
throw '@list:' + code;
368364
}
369365

370366
return res;
371367
}
372368
});
369+
370+
function defaultResponseDataParse(data) { return data }
371+
function defaultTransform(data) { return data }

src/ams/configs/alias/field.js

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { deepExtend, get } from '../../../utils';
1+
/* eslint-disable complexity,no-new,max-depth */
2+
3+
import { deepExtend, responseHandler } from '../../../utils';
24
import * as fieldGetSet from '../field-get-set';
35
import { httpRequestTypeExcludeGet } from '../../request';
46

@@ -171,19 +173,13 @@ export const SELECT_REMOTE = {
171173
$field.loading = true;
172174
const res = await remoteConfig.request.call(this, $field, query, isBackfill);
173175
$field.loading = false;
174-
175-
let data = get(res.data, remoteConfig.dataPath);
176-
let successCode;
177-
178-
if (typeof remoteConfig.successCode !== 'undefined') {
179-
successCode = remoteConfig.successCode;
180-
} else {
181-
successCode = this.getConfig('resource.api.successCode');
182-
}
183-
if (
184-
res.data.code === successCode &&
185-
data
186-
) {
176+
// eslint-disable-next-line no-unused-vars
177+
const { isSuccess, data } = responseHandler.call(this, res, '', {
178+
dataPath: remoteConfig.dataPath, // 'data.list',
179+
successCode: remoteConfig.successCode || this.getConfig('resource.api.successCode'),
180+
codePath: remoteConfig.codePath || this.getConfig('resource.api.code') || 'code'
181+
});
182+
if (isSuccess && data) {
187183
const options = remoteConfig.transform.call(this, $field, data);
188184
const optionsEntity = options.reduce((obj, cur) => Object.assign(obj, { [cur.label]: cur.value }), {});
189185
if (remoteConfig.isCache) {

src/utils/api.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { get as lodashGet } from 'lodash';
2+
3+
const defaultGetter = {
4+
codePath: 'code',
5+
successCode: 0,
6+
dataPath: 'data',
7+
totalPath: 'total',
8+
listPath: 'list',
9+
messagePath: 'msg',
10+
};
11+
12+
/**
13+
* 从 API Response 中获取相关字段,如是否成功、total、data 等
14+
* https://github.com/vipshop/ams/pull/125
15+
*
16+
* @param {Object} response : api response data
17+
* @param {String} action : read/update/list/delete 增删改查
18+
* @param {Object} actionGetter : 适配更多接口的返回值
19+
*
20+
* ams 默认接口数据结构: https://vipshop.github.io/ams/api/api.html#%E9%80%9A%E7%94%A8%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84
21+
*
22+
* -------常规请求----------
23+
* {
24+
[codePath]: [successCode],
25+
[dataPath]: String,
26+
[messagePath]: String
27+
* }
28+
*
29+
*
30+
* ------- 列表请求----------
31+
* {
32+
[codePath]: [successCode],
33+
[dataPath]: {
34+
[dataPath.listPath]: [],
35+
[dataPath.totalPath]: Number,
36+
},
37+
[messagePath]: String
38+
* }
39+
*
40+
*
41+
*/
42+
export function responseHandler(response, action, actionGetter) {
43+
const configGetter = this.getConfig(`resource.api.${action}.getter`);
44+
const getter = {
45+
...defaultGetter,
46+
...actionGetter,
47+
...configGetter
48+
};
49+
50+
const code = lodashGet(response.data, getter.codePath); // api response(success/result)对应的值
51+
// eslint-disable-next-line
52+
const isSuccess = code == getter.successCode;
53+
return {
54+
code,
55+
getter,
56+
isSuccess,
57+
data: lodashGet(response.data, getter.dataPath),
58+
total: lodashGet(response.data, getter.totalPath),
59+
message: lodashGet(response.data, getter.messagePath),
60+
};
61+
}

src/utils/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from './dom';
44
export * from './function';
55
export * from './tools';
66
export * from './localstorage';
7+
export * from './api';
78

89
export function get(object, path) {
910
path = path.split('.');

0 commit comments

Comments
 (0)