自动生成API接口封装(apiGenerator)
这个问题一直在脑海里挥之不去,一直以为网上可以找到对应的demo。然而,事实上,是我过于天真了,总觉得可以找到,一直都在苦苦寻找。实属无奈,看来还在是自己动手,丰衣足食啦。之后,就有了这一篇文章的出现~,嘎嘎嘎。
目的
为了以后修改接口方便,如果项目很大,在每一个页面里修改接口的话,很麻烦,所以封装在一个文件里,找起来也方便。
axios封装
在这里就不过多的解释与说明了,这个网上一堆一堆的,自己也可以按着官网封装axios。
apiGenerator封装之文件头部资源引入
这里就没啥好阐述的啦,看个人喜好而定。怎么舒服就怎么引入。
import axios from './request'; // # axios封装,api接口封装统一管理(这个自行封装处理)。
import _ from 'lodash'; // Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。
import qs from 'qs'; // qs是一个npm仓库所管理的包,可通过npm install qs命令进行安装。
apiGenerator封装之axios请求方式函数
此处,需要特别留个小心眼的地方是,axios 请求方式的大小写问题。我们在此可以使用 JavaScript 提供的字符串大小写转换的方法。
toLowerCase将字符串转为小写,实例:'LOWER'.toLowerCase();toUpperCase将字符串转为大写,实例:'upper'.toUpperCase();
const getMethodType = function(api) {
// axios 目前只支持请求方式有4种,这里如果觉得没必要,也可以去掉。
if (api.method && ['GET', 'POST', 'PUT', 'DELETE'].includes(api.method.toUpperCase())) {
return api.method;
} else {
throw new Error('未声明请求方法!');
}
};
apiGenerator封装之axios路径参数函数
const getPathParams = function(url) {
let regex = /{([^}]+)}/g;
let pathParams = [];
let currentMatch;
while ((currentMatch = regex.exec(url))) {
pathParams.push(currentMatch[1]);
}
return pathParams;
};
apiGenerator封装之axios的使用处理函数
let prepareAjaxMethod = api => (options = {}) => {
let method = getMethodType(api);
let pathParams = getPathParams(api.url);
let newUrl = pathParams.reduce((url, pathParam) => {
let paramVal = options.pathParams[pathParam];
if (paramVal || paramVal === 0) {
return url.replace(`{${pathParam}}`, paramVal);
} else {
throw new Error(`${url} has invalid path params.`);
}
}, api.url);
if (!_.isEmpty(options.queryParams)) {
newUrl = `${newUrl}?${qs.stringify(options.queryParams)}`;
}
// hack for axios headers
if (_.isUndefined(options.data)) options.data = {};
Reflect.deleteProperty(options, 'pathParams');
Reflect.deleteProperty(options, 'queryParams');
options = _.merge(
{
url: newUrl,
method,
},
options
);
return axios(options);
};
apiGenerator封装之生成axios接口api数据集,暴露外部使用的函数
export const generate = function(apiObj) {
_.forIn(apiObj, (v, k) => {
let newVal = {};
v.forEach(api => {
newVal[api.name] = prepareAjaxMethod(api);
});
apiObj[k] = newVal;
});
return apiObj;
};
apiGenerator完整代码
import axios from './request';
import _ from 'lodash';
import qs from 'qs';
let getMethodType = function(api) {
if (api.method && ['GET', 'POST', 'PUT', 'DELETE'].includes(api.method.toUpperCase())) {
return api.method;
} else {
throw new Error('未声明请求方法!');
}
};
let getPathParams = function(url) {
let regex = /{([^}]+)}/g;
let pathParams = [];
let currentMatch;
while ((currentMatch = regex.exec(url))) {
pathParams.push(currentMatch[1]);
}
return pathParams;
};
let prepareAjaxMethod = api => (options = {}) => {
let method = getMethodType(api);
let pathParams = getPathParams(api.url);
let newUrl = pathParams.reduce((url, pathParam) => {
let paramVal = options.pathParams[pathParam];
if (paramVal || paramVal === 0) {
return url.replace(`{${pathParam}}`, paramVal);
} else {
throw new Error(`${url} has invalid path params.`);
}
}, api.url);
if (!_.isEmpty(options.queryParams)) {
newUrl = `${newUrl}?${qs.stringify(options.queryParams)}`;
}
// hack for axios headers
if (_.isUndefined(options.data)) options.data = {};
Reflect.deleteProperty(options, 'pathParams');
Reflect.deleteProperty(options, 'queryParams');
options = _.merge(
{
url: newUrl,
method,
},
options
);
return axios(options);
};
export const generate = function(apiObj) {
_.forIn(apiObj, (v, k) => {
let newVal = {};
v.forEach(api => {
newVal[api.name] = prepareAjaxMethod(api);
});
apiObj[k] = newVal;
});
return apiObj;
};
apiGenerator使用完整例子
// 引入apiGenerator方法
import { generate } from '../utils/apiGenerator'
// 接口api配置
const form = [{name: 'add', url: '/form/add', method: 'POST' }];
const field = [{ name: 'save', url: '/field/get', method: 'GET' }];
const api = {form, field};
export default generate(api);
更进一步,优化。可以使用 前端工程化动态引入文件(require.context),这样就只要去配置接口api配置就好了,无需再引入每个接口api配置文件。省心省事。
例如:把上面的 form, field 封装成模块,然后统一在index.js 文件处理,如下:
// 引入apiGenerator方法
import { generate } from '../utils/apiGenerator'
// 使用 require.context 动态加载modules文件的 api配置 模块
const requiredModules = require.context('./', false, /\.js$/)
const api = {}
requiredModules.keys().forEach(fileName => {
api[fileName] = requiredModules(fileName).default || requiredModules(fileName)
})
export default generate(api);
到此就完结了,谢谢光临。