繁体   English   中英

SetInterval 永远保持运行并且不会停止

[英]SetInterval Keeps Running forever and doesnt stop

我已经被这个问题困住了很长一段时间。 我正在制作一个矩阵风格的主题博客,当我的商店中的 displayMatrix 雨 state 变为 true 时,在后台显示矩阵雨效果,当 displayMatrix 变为 false 时停止显示矩阵雨效果。 我需要使用 setInterval 来绘制矩阵雨效果,在 setInterval 内部我称之为“绘制”function,它内部有一个循环,使用 canvas 工具在背景中绘制矩阵雨字符。 我遇到的问题是,当我将 displayMatrix state 更改为 true,而不是稍后更改为 false 时,循环继续运行,我从未在控制台日志中看到 'id being clear is => #' 即使我有将 displayMatrix state 更改为 false。 我试图在以下沙箱中模仿我的代码的准系统,以便您可以看到代码https://playcode.io/933189/的整体结构。 我正在使用 reacts 内置的 useReducer/useContext 挂钩代替 redux。 我注意到的另一个奇怪的事情是,在代码沙箱中,当我将 displayMatrix state 更改为 true,然后将其变为 false,它至少会停止控制台中的“运行矩阵雨绘图代码”,但在我的原始代码中在 VisualStudio Code 上,我一直在控制台中看到“运行矩阵雨绘图代码”,它基本上永远运行,直到它用完 memory

import React from 'react';
import {useEffect, useContext, useState} from 'react';
import {GlobalStore} from '../Store.jsx';


export function App(props) {

  const [state, dispatch] = useContext(GlobalStore);

  const [intervalId, setIntervalId] = useState(0);

  useEffect(() => {

    const draw = () => {
      // pretend 100 is the width of the screen
      for (let i = 0; i < 100; i += 1)
      {
        console.log("run matrix rain drawing code");
      }
    }

    // if we want to diplay the matrix rain
    if (state.displayMatrix) {
        // only create an interval when interval does
        // not already exist
        if (intervalId === 0) {
            const id = setInterval(draw, 90);
            console.log("id being set is => " + id);
            setIntervalId(id);
        }
        else {
            console.log("id being cleared is => " + intervalId);
            clearInterval(intervalId);
            setIntervalId(0);
        }
    }
    // if we want to stop matrix rain
    else {
        console.log("id being cleared is => " + intervalId);
        clearInterval(intervalId);
        setIntervalId(0);
    }

  }, [state.displayMatrix])

  return (
        <div>
            <div onClick={() => dispatch({type: 'CHANGE_MATRIX_RAIN_BACKGROUND_DISPLAY_STATE'})}>Matrix Display {state.displayMatrix ? 'Off' : 'On'}</div>
        </div>
  )

}

我有这个时间Counter helper class

import { setIntervalAsync, clearIntervalAsync, SetIntervalAsyncTimer } from 'set-interval-async/fixed';

export class TimeCounter {
  private interval: SetIntervalAsyncTimer | undefined;
  private onRepeat: () => any;
  private onStop: () => any;

  constructor(onRepeat: () => any, onStop: () => any) {
    this.onRepeat = onRepeat;
    this.onStop = onStop;
  }

  startCounter(milliseconds: number) {
    if (!this.isActive()) {
      this.interval = setIntervalAsync(async () => {
        this.onRepeat();
      }, milliseconds);
    }
  }

  stopCounter(): void {
    if (this.interval !== undefined) {
      this.onStop();
      clearIntervalAsync(this.interval);
      this.interval = undefined;
    }
  }

  isActive(): boolean {
    return this.interval !== undefined;
  }
}

用法:

export function useCounter() {
  const counter = new TimeCounter(onRepeatCounter, () => null);
  const [result, setResult] = useState(0);

  useEffect(() => {
    if (!counter.isActive() && defaultDate === undefined) {
      counter.startCounter(1000);
    }
    return () => counter.stopCounter();
  });

  function onRepeatCounter() {
    // Custom functionality
    setResult((val) => val + 1);
  }

  return result;
}

playcode 似乎工作正常,只需按 Show More 即可查看日志结束。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM