自定义hooks封装轮询接口逻辑
轮询使用react-query refetchInterval方法
export interface IDeliveryOpLogRes {
deliveryInfoList: IDeliveryOpLogInfo[];
hasNext: boolean;
}
export interface IDeliveryOpLogInfo {
adviceQa: any;
attachInfoText: string;
attachMsg: string;
deliveryLevelStr: string;
deliveryNodeDesc: string;
deliveryNodeMethod: string;
deliveryNodeStep: string;
deliveryNodeTypeStr: string;
deliveryProcessName: string;
deliveryStatus: DeliveryOpLogStatusEnum;
attachStackTrace: string;
id: number;
requestIdentify: string;
timestampStr: string;
}
/** 无数据下,最大轮询次数,避免异常状况无限轮询 */
const OP_LOG_MAX_EMPTY_POLLING_COUNT = 100;
/** 轮询间隔 */
const OP_LOG_POLLING_INTERVAL = 3000;
// 自定义hooks接受两个参数,接口参数id和请求接口的函数
function useOpLog(operationId: string, logQueryFn: (operationId: string, nextIndex?: number) => Promise<IDeliveryOpLogRes>) {
const [emptyPollCount, setEmptyPollCount] = useState(0); // 记录无数据时的轮询次数
const [nextLogIndex, setNextLogIndex] = useState<number>(null); // 轮询下一次请求的第二个参数
const [logs, setLogs] = useState<IDeliveryOpLogInfo[]>([]); // 轮询结果得到的所有数据
const opLogQ = useQuery(
['getDeliveryOpLog', operationId],
() => logQueryFn(operationId, nextLogIndex),
{
enabled: !!operationId, // 决定是否发起请求
refetchInterval: (data) => {
// 判断是否轮询的条件 返回轮询间隔轮询接口 返回false不轮询接口
if (emptyPollCount >= OP_LOG_MAX_EMPTY_POLLING_COUNT) {
return false;
}
if (data?.hasNext && operationId) {
return OP_LOG_POLLING_INTERVAL;
}
return false;
},
onSuccess: (data) => {
const { deliveryInfoList = [] } = data;
if (deliveryInfoList.length) {
setLogs(prev => prev.concat(deliveryInfoList)); // 新数据合并到原数据中
}
// 处理hasNext
if (data.hasNext) {
if (!deliveryInfoList.length) {
setEmptyPollCount(prev => prev + 1); // 请求无数据时开始计数
} else {
setNextLogIndex(deliveryInfoList[deliveryInfoList.length - 1].id); // 获取下次请求的第二个参数
setEmptyPollCount(0); // 接口hasNext返回false 重新开始计数 不再轮询接口
}
}
},
},
);
useEffect(() => {
setEmptyPollCount(0);
setNextLogIndex(null);
setLogs([]);
}, [operationId]);
return {
logs: [...logs].reverse(), // 新生成的数据在上面显示
isLoading: opLogQ.isFetching, // 接口是否在加载
hasNext: opLogQ.data?.hasNext,
};
}