背景
多个页面仅调用接口不同,功能相似
问题
多个路由使用了一个组件,该组件中需要定时调用接口,切换路由时观察接口发现存在多个定时器,且另一个页面的定时器并未消除
扼要代码如下:
const props = defineProps({
//接收函数
request: {
type: Function,
default: undefined
}
});
const resolveListRequest = async requestInstance => {
if (typeof props.request !== 'function') return;
const request = requestInstance({
page: queryParams.page,
size: queryParams.size,
keyword: queryParams.keyword
});
return request instanceof Promise ? await request : request;
};
//页面分页接口以及定时器
const getList = async () => {
const requestInstance = props.request;
if (typeof requestInstance !== 'function') return;
const data = await resolveListRequest(requestInstance);
if (!data) return;
list.value = data.list;
total.value = data.total;
timer = setTimeout(async function () {
await getList();
}, 1000);
};
onMounted(() => {
if (props.request) {
getList();
}
});
// 清除定时器
onUnmounted(() => {
timer && clearTimeout(timer);
});
解决办法
我们知道setTimeout会等待调用结束后才会发起下一次调用,通过不断debug我们发现,当发起新的一次接口请求但是接口还未有返回值时,组件已经调用了onUnmounted并清除了之前的定时器,组件完成了使命,但是紧接着接口吐出了返回值并又生成了新的定时器,导致定时器无法被彻底清除的问题,所以我们需要保证 在清除掉所有的定时器后当前组件不会再有接口调用
因此,我们可以——
设置标识isclear判断定时器是否消除,虽然笨了点,但是简单有效
let isclear = false;
const getList = async () => {
if (isclear) return;
const requestInstance = props.request;
if (typeof requestInstance !== 'function') return;
const data = await resolveListRequest(requestInstance);
if (!data) return;
list.value = data.list;
total.value = data.total;
timer = setTimeout(async function () {
await getList();
}, 1000);
};
// 清除定时器
onUnmounted(() => {
timer && clearTimeout(timer);
isclear = true;
});