2021SC@SDUSC
文章目录
概述
本周分析学习amis
的API请求的封装库api.ts
,里面主要是amis
对网络请求的自我封装处理方法。
关键函数
normalizeApi
处理 api,使其成为标准化、规范化的 API 对象。
// 用于正则匹配请求方法的正则表达式
const rSchema = /(?:^|raw\:)(get|post|put|delete|patch|options|head):/i;
export function normalizeApi(
api: Api,
defaultMethod: string = 'get' // 默认方法为 get 请求
): ApiObject {
if (typeof api === 'string') {
// 当 api 还是字符串类型时,将其处理成 API 对象
let method = rSchema.test(api) ? RegExp.$1 : ''; // 匹配 api 中的请求方法,无则为空
// method 存在时将其去除,剩下部分为请求的 url
method && (api = api.replace(method + ':', ''));
api = {
method: (method || defaultMethod) as any, // 无则为默认的 defaultMethod
url: api
};
} else {
// 说明 api 已被处理过了,克隆 api
api = {
...api
};
}
return api;
}
从这段代码以及结合以前的代码,我们可以发现,大的开发项目中对于对象的处理很少是在原数据上直接修改,而是对目标数据进行克隆后再修改,返回新的对象,原始对象保持不变。为什么呢?第一,该对象可能在多处使用,一处改变处处受其影响。第二,原来数据的丢失不能再恢复,如果之后再需要时将不能再次获得。
buildApi
建立请求 api,该函数将 api 封装成一个完整的实体,对所有涉及到的请求类别都完美的适配处理。
export function buildApi(
api: Api,
data?: object,
options: {
autoAppend?: boolean; //
ignoreData?: boolean; // 是否忽略请求体数据
[propName: string]: any;
} = {
}
): ApiObject {
api = normalizeApi(api, options.method); // api 请求标准化
const {
autoAppend, ignoreData, ...rest} = options; // 可选参数解析
// rest 是自定义的请求配置项
api.config = {
...rest
};
// api.method 来自于规则化后的 api.method | options 中的自定义配置项 | 默认的 get
// 其实此时 api.method 已经满足要求了,我不太清楚这样反复检测的目的,难道还有特殊情况?
api.method = (api.method || (options as any).method || 'get').toLowerCase();
if (!data) {
// 没有数据,直接不用考虑了
return api;
} else if (
// 携带的 data 是 FormData(表单数据) | Blob(二进制文件) | ArrayBuffer(buffer数组)
data instanceof FormData ||
data instanceof Blob ||
data instanceof ArrayBuffer
) {
api.data = data; // 可直接传输,直接赋给 api.data 字段
return api;
}
// 下面处理 get 请求中携带在 url 中的数据
// 这里也不太理解,api.url = api.url 不是赋值语句吗?恒成立啊
// raw = api.url
const raw = (api.url = api.url || '');
// 找到 api.url 中的 ?
const idx = api.url.indexOf('?');
// 包含 ?
if (~idx) {
// # 后的参数是该页面内的参数,不是请求数据;如果包含 # ,其后不用考虑
const hashIdx = api.url.indexOf('#');
// 将其处理成键值对的参数列表
const params = qsparse(
// 从 ? 到 #
api.url.substring(idx + 1, ~hashIdx ? hashIdx : undefined)
);
api.url =
// 将主 url 处理后再与其余部分结合
tokenize(api.url.substring(0, idx