Web Worker 中的 clearInterval 不停止计时器

clearInterval in web worker not stopping timer

我的问题在这里被问过一次: clearInterval in webworker is not working

解决方案似乎很清楚,但出于某种原因,它还不适用于我。我有一个网络工作者正在将一个间隔发送回主线程。我希望能够使用 clearInterval 停止间隔,但它不起作用。

我的设置与上一个问题中的建议完全相同,但仍然没有成功。我添加了一些 console.logs 来验证我在正确的块中。 “停止”在应该的时候记录到控制台,但计时器不会停止发布到主线程。

有人能看出这是怎么回事吗?

谢谢

worker.js

let mytimer;

self.onmessage = function(evt) {
    if (evt.data == "start") {
        console.log("start")
        var i = 0;
        
        mytimer = setInterval(function() {
            i++;
            postMessage(i);
        }, 1000);
        
    } else if (evt.data == "stop") {
        console.log("stop")

        clearInterval(mytimer);
    }
};

然后当 timer.time 高于或低于某个值(在本例中为 2000)时,我从我的 React 挂钩中调用它

main.js


  const worker = new myWorker()

 useEffect(() => {

    worker.addEventListener('message', function(e) {

      //from interval in the worker
      console.log('Message from Worker: ' + e.data);
    })

    if(timer.time > 2000){
      worker.postMessage("start")
    }else{

      worker.postMessage("stop")
    }
  },[timer.time])

您还应该在开始新的间隔时清除间隔。如果你不这样做,你之前的间隔将保持运行,你将失去清除它的能力:

let mytimer;

self.onmessage = function(evt) {
  console.log(evt.data)
  
  if(evt.data === 'start' || evt.data === 'stop') {
    clearInterval(mytimer);
  }

  if (evt.data == "start") {
    var i = 0;

    mytimer = setInterval(function() {
      i++;
      postMessage(i);
    }, 1000);

  }
};

您应该创建一个工人实例,并将其存储为 ref:

const worker = useRef()

useEffect(() => {
  worker.current = new myWorker()

  return () => {
    worker.current.terminate();
  }
}, [])

不相关,但除此之外,每当 timer.time 更改时,useEffect 都会添加一个新的事件侦听器,而不清除前一个。我会把它分成 2 useEffect 个块,一个用于发送(可以与 worker 的创建相结合),另一个用于接收。

useEffect(() => {
  const eventHander = e => {
    //from interval in the worker
    console.log('Message from Worker: ' + e.data);
  }

  worker.current.addEventListener('message', eventHander)
  
  return () => {
    worker.current.removeEventListener('message', eventHander)
  }
}, [])

useEffect(() => {
  worker.current.postMessage(timer.time > 2000 ? 'start' : 'stop')
}, [timer.time])

我不确定网络工作者,但我非常熟悉在 useEffect 中使用间隔。由于每次依赖项更改 (timer.time) 时都会调用 useEffect,因此您需要将间隔存储在 useRef 中,除非您要在依赖项下次更改之前清除它