我们已经实现了自动把同一时刻的请求合并成多个 fetch,并统一渲染。
存在问题
但是又遇到了一种新的场景:就是不同组件,发送相同参数的相同请求时,这在原来的场景下,还是会发两个相同的请求。
而想要优化,只能把请求移到外层,通过参数分别透传给两个组件。
那,我们这个 fetch 组件能不能直接把这个工作给做了呢,让用户自由地发送请求,而由 fetch 组件来做优化呢?
具体实现
我们来思考一下,这个思路,就是把请求删减为一个,而把成功处理和失败回调变成多个,就可以啦。
细节上来说的话,就是遇到同名且相同参数的请求时,原本会作增加新请求操作,而现在直接跳过,同时把回调函数加到对应的成功及失败回调中。
那我们先来第一步:
回调变为数组
首先是增加一些新的定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
type ISuccessCallback = (obj: IObject) => void;
type IErrorCallback = (err: Error) => void;
interface IBatchItem { name: string; options: IFetchOptions; successList: ISuccessCallback[]; errorList: IErrorCallback[]; }
interface IBatchMap { [url: string]: IBatchItem; }
|
然后便是处理这些逻辑的地方:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| let batchList: IBatchMap[] = [];
const sendRequestBatch: (tempRequestMap: IBatchMap) => void = ( tempRequestMap ) => { const batchData = Object.values(tempRequestMap).reduce( (pre: IObject, cur: IBatchItem) => { const { name: requestName, options } = cur; return { ...pre, [requestName]: deepStringify(options.data) }; }, {} );
fetchBase('/api/batch', { data: batchData }) .then((res: IBatchResponse) => { withBatch(() => { Object.keys(res).forEach((key) => { const { code, message, msg, data } = res[key]; if (!tempRequestMap[key]) { return; } const { successList: successCallbackList, errorList: errorCallbackList } = tempRequestMap[key]; if (code !== 200) { const err: IErrorResponse = new Error( (message || msg) ?? '系统繁忙,请稍后再试' ); err.code = code; errorCallbackList.forEach( (errorCallback: IErrorCallback) => { if (errorCallback) { errorCallback(err); } } ); } else { successCallbackList.forEach( (successCallback: ISuccessCallback) => { if (successCallback) { successCallback(data); } } ); } }); }); }) .catch((err: Error) => { Object.keys(tempRequestMap).forEach((key) => { const { errorList: errorCallbackList } = tempRequestMap[key]; errorCallbackList.forEach((errorCallback: IErrorCallback) => { if (errorCallback) { errorCallback(err); } }); }); }); };
|
跳过同参数请求
第二步便是在 addRequest
增加跳过逻辑和增加回调操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
const addRequest: (requestItem: IRequestItem) => void = (requestItem) => { const { name, options, success, error } = requestItem;
const stringifyData = JSON.stringify(options?.data); const equalIndex = Math.max( -1, ...batchList.map((item: IBatchMap, index: number) => item[name] && JSON.stringify(item[name].options?.data) === stringifyData ? index : -1 ) ); if (equalIndex > -1) { batchList[equalIndex][name].successList.push(success); batchList[equalIndex][name].errorList.push(error); return; }
const batchItem = { name, options, successList: [success], errorList: [error] };
const lastIndex = Math.max( -1, ...batchList.map((item: IBatchMap, index: number) => item[name] ? index : -1 ) );
};
|