ht_hooks
Version:
ht React 业务 Hooks
68 lines • 2.91 kB
JavaScript
//!在请求成功或失败之后,隔一段时间自动重新请求,形成“循环请求”
//!每隔 pollingInterval 毫秒重新请求一次
//!根据 pollingWhenHidden 判断
//!如果连续出错次数超过 pollingErrorRetryCount,停止轮询
//!页面恢复可见后,立刻再发请求
import { useRef } from 'react';
import useUpdateEffect from '../../../useUpdateEffect';
import isDocumentVisible from '../utils/isDocumentVisible';
import subscribeReVisible from '../utils/subscribeReVisible';
var usePollingPlugin = function (fetchInstance, _a) {
var pollingInterval = _a.pollingInterval,
_b = _a.pollingWhenHidden,
pollingWhenHidden = _b === void 0 ? true : _b,
_c = _a.pollingErrorRetryCount,
pollingErrorRetryCount = _c === void 0 ? -1 : _c;
var timerRef = useRef(); //存储轮询定时器
var unsubscribeRef = useRef(); //用于取消可见性恢复订阅
var countRef = useRef(0); //记录连续错误的次数
var stopPolling = function () {
var _a;
if (timerRef.current) {
clearTimeout(timerRef.current); //清除当前轮询定时器
}
(_a = unsubscribeRef.current) === null || _a === void 0 ? void 0 : _a.call(unsubscribeRef); //清理“页面可见性恢复”的订阅
};
useUpdateEffect(function () {
if (!pollingInterval) {
stopPolling(); //如果 pollingInterval 为 0 或 undefined,停止轮询
}
}, [pollingInterval]);
if (!pollingInterval) {
//#如果没配置 pollingInterval,插件啥也不干
return {};
}
return {
onBefore: function () {
stopPolling(); //每次请求前先停掉上一轮的轮询,避免多次定时器叠加
},
onError: function () {
countRef.current += 1; //如果请求出错,错误计数加 1
},
onSuccess: function () {
countRef.current = 0; //如果请求成功,错误计数清零
},
onFinally: function () {
if (
//如果 允许错误次数 是无限次,或者有限次但还没超限,就继续重新请求
pollingErrorRetryCount === -1 || pollingErrorRetryCount !== -1 && countRef.current <= pollingErrorRetryCount) {
timerRef.current = setTimeout(function () {
if (!pollingWhenHidden && !isDocumentVisible()) {
//如果页面不可见 (document.hidden) 且不允许隐藏时暂停轮询
unsubscribeRef.current = subscribeReVisible(function () {
fetchInstance.refresh(); //页面恢复可见时refresh重新请求(又会触发onFinally轮询)
});
} else {
fetchInstance.refresh();
}
}, pollingInterval);
} else {
countRef.current = 0; //!超过最大错误次数时:不设置下一个定时器(没有 setTimeout),相当于彻底停掉了轮询
}
},
onCancel: function () {
stopPolling();
}
};
};
export default usePollingPlugin;