const定义的数据可以更改么?
基本数据类型不可以修改
引用数据类型绑定不可变,但内容可以修改,变量指向的内存地址不变,但对象内部属性或数组元素可以修改。
若需完全不可变,可使用 Object.freeze()(浅冻结)或不可变库(如 Immutable.js)
用setTimeout模拟setInterval?
可以使用 setTimeout 递归调用来模拟 setInterval,这样可以更灵活地控制每次执行的间隔,并且避免 setInterval 的一些潜在问题(例如任务执行时间超过间隔时间导致堆积)。
使用 async/await 控制间隔(适用于异步任务)
如果回调函数是异步的(如 fetch 请求),可以用 async/await 确保每次任务完成后再等待:
async function customAsyncInterval(callback, delay) {
let isRunning = true;
const stop = () => {
isRunning = false;
};
const run = async () => {
while (isRunning) {
await callback(); // 等待回调完成
await new Promise(resolve => setTimeout(resolve, delay)); // 等待 delay
}
};
run();
return s
// 使用示例 const stop = customAsyncInterval(async () => { console.log("执行异步任务"); await new Promise(resolve => setTimeout(resolve, 500)); // 模拟异步操作 }, 1000); // 5 秒后停止 setTimeout(stop, 5000);
------------- | ---------------------------- | | 方法**** | 特点**** | | setInterval | 固定间隔执行,如果任务执行时间 > 间隔,会导致任务堆积 | | setTimeout 模拟 | 每次任务完成后才重新计时,避免堆积,更可控 | | async/await 版 | 适用于异步任务,确保每次任务完成后再等待
每隔5s打印123
function startInterval(callback, delay) {
let timerId;
const repeat = () => {
callback();
timerId = setTimeout(repeat, delay);
};
timerId = setTimeout(repeat, delay); // 首次执行
return () => clearTimeout(timerId); // 返回清除函数
}
// 使用
const stopPrinting = startInterval(() => {
console.log("123");
}, 5000);
// 30 秒后停止
setTimeout(() => {
stopPrinting();
console.log("已停止");
}, 30000);
import { useEffect, useRef, useState } from 'react';
const usePolling = (apiFn, interval = 10000, immediate = true) => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const pollingRef = useRef(null);
// 执行请求
const fetchData = async () => {
if (!apiFn) return;
setIsLoading(true);
try {
const result = await apiFn();
setData(result);
setError(null);
} catch (err) {
setError(err);
} finally {
setIsLoading(false);
}
};
// 启动轮询
const startPolling = () => {
if (pollingRef.current) return; // 避免重复启动
const poll = async () => {
await fetchData();
pollingRef.current = setTimeout(poll, interval);
};
poll(); // 立即执行一次
};
// 停止轮询
const stopPolling = () => {
if (pollingRef.current) {
clearTimeout(pollingRef.current);
pollingRef.current = null;
}
};
// 组件挂载时自动启动(如果 immediate=true)
useEffect(() => {
if (immediate) {
startPolling();
}
return stopPolling; // 组件卸载时自动停止
}, [apiFn, interval, immediate]);
return { data, error, isLoading, startPolling, stopPolling };
};
export default usePolling;
import React from 'react';
import usePolling from './usePolling';
// 模拟 API 请求函数
const fetchUserData = async () => {
const response = await fetch('https://api.example.com/user');
return response.json();
};
const UserPollingComponent = () => {
const { data, error, isLoading, startPolling, stopPolling } = usePolling(
fetchUserData,
10 * 60 * 1000, // 10分钟
true // 立即启动
);
return (
<div>
<h1>用户数据轮询</h1>
{isLoading && <p>加载中...</p>}
{error && <p style={{ color: 'red' }}>错误: {error.message}</p>}
{data && (
<div>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
)}
<button onClick={startPolling}>开始轮询</button>
<button onClick={stopPolling}>停止轮询</button>
</div>
);
};
export default UserPollingComponent;