龙空技术网

在 JS 中使用 setInterval() 重叠执行问题

启辰8 109

前言:

今天看官们对“js间隔执行”大约比较着重,各位老铁们都需要了解一些“js间隔执行”的相关内容。那么小编在网摘上搜集了一些对于“js间隔执行””的相关知识,希望小伙伴们能喜欢,咱们一起来学习一下吧!

在某些情况下,我们需要以指定的时间间隔执行一段代码进行多次迭代。 JavaScript 附带了一些令人惊叹的内置对象和函数,其中两个解决我们问题的函数是 setInterval(callback, Interval) 和 setTimeout(callback, Delay),其中这些函数在指定的延迟或之后安排回调函数的下一次执行 间隔。

我们来对比一下两段代码

代码片段 1:使用 setInterval()

const [currentTime, setCurrentTime] = useState(new Date());useEffect(() => {  const timer = setInterval(() => {    setCurrentTime(new Date());  }, 1000);  // Clean up the timer when the component unmounts  return () => {    clearInterval(timer);  };}, []); const formattedTime = currentTime.toLocaleTimeString([], {    hour: "numeric",    minute: "2-digit",  });return (    <div className="header">      <span className="current-time">{formattedTime}</span>    </div>  );

在这里,我们在 React 的 useEffect 钩子中设置和管理一个计时器,该计时器每 1000 毫秒(1 秒)运行一次函数 setCurrentTime(new Date()) 来每秒更新当前时间,该时间在格式化后在我们的应用程序标头中使用 与格式化时间。

需要注意的一个关键点是,我们在 cleanUp 函数中使用 clearInterval(timer) 来确保正确清除组件卸载时最初由 setInterval() 设置的间隔。 这是防止内存泄漏的最佳实践,因为在删除组件后保留运行间隔可能会消耗不必要的资源。

如果回调执行时间比间隔长,或者每次迭代时回调执行时间不同,并且在我们处理 Ajax 调用的情况下,下一个回调可能会在前一个回调完成之前开始,从而在严格计时的场景中导致潜在问题 必要的。

使用 setInterval,回调会被安排以固定的时间间隔运行,无论之前的执行是否已完成。 setInterval() 没有内置的重叠保护。

代码片段 2:使用 setTimeout() 和递归

useEffect(() => {  let isMounted = true; // Flag to track component mount status  const updateCurrentTime = () => {    if (!isMounted) return; // Terminate recursion when component unmounts    setCurrentTime(new Date());    setTimeout(updateCurrentTime, 1000); // Schedule the next update after 1 second  };  updateCurrentTime(); // Start the updates  return () => {    isMounted = false; // Mark the component as unmounted  };}, []);

虽然其他功能相同,但 useEffect 有一些修改,我们递归地使用 setTimeout() 函数每秒更新当前时间,并使用 isMounted 标志在卸载组件期间清除间隔。

这里需要理解的关键是,每个后续的 setTimeout() 都是在前一个 setTimeout() 的回调中设置的。 这意味着只有在上一次执行完成后才会安排下一次执行。 JavaScript 的事件循环确保在当前迭代完成之前不会安排函数的下一次迭代。

因此,您会得到一系列执行,这些执行之间至少有 1 秒的延迟。 这种顺序执行模式有助于避免重叠,并确保每次执行在下一次执行开始之前完成。

setTimeout() 的递归使用可确保仅在当前执行完成后安排下一次执行,因为每个 setTimeout() 调用都发生在前一个 setTimeout() 调用的回调中。 这种方法保证了回调在下一次执行开始之前有足够的时间完成。

结论

虽然 setInterval() 和 setTimeout() 都是安排时间间隔的好方法,但注意对执行时间的精确控制很有用。 递归 setTimeout() 方法允许您独立控制每次执行的时间,这在每次迭代的执行时间变化时非常有用,并且本质上可以防止重叠执行。

感谢您在接下来的休息时间里阅读到目前为止的内容:)我可能会为您写一些新的东西!

标签: #js间隔执行