javascript 我想做我自己的事件循环侦听器,但它阻塞了调用堆栈如何像处理任何事件一样处理它

yrefmtwq  于 2023-01-07  发布在  Java
关注(0)|答案(1)|浏览(111)

我希望我的代码chick如果一个数据被更改,然后做一些事情,所以我想出了这个

function autoRendring(list,unchangedlist){
    while(true){

        while(list==unchangedlist){
         //Busy waiting  
        }
          
        console.log("renderd !")
        render(list)
        unchangedlist=list
    }

我怎么能执行这个fuchion与出阻塞的主线程我已经阅读了有关事件循环和浏览器如何处理他们分别从主头部,但我仍然不知道该怎么做
}
它只会阻塞主线程
我想用c#做一些类似这样东西

using System.Threading;

int x = 0;
int y = x;

Thread t = new Thread(() => render(ref x,ref y));
Thread t2 = new Thread(() => change(ref x,ref y));

static void render(ref int x,ref int y)
{
    while (true)
    {
      
        while (x == y)
        {
      

        }
        
        Console.WriteLine(" x has changed and renderd !");
        y=x;
    }
}
static void change(ref int x,ref int y)
{
    while (true)
    {

        Console.WriteLine("inter x ");
        Console.WriteLine("x is " + x + "  and y is " + y);
        x = int.Parse(Console.ReadLine());
    }
}

t2.Start();
t.Start();
wztqucjr

wztqucjr1#

代码实际上存在多个问题:
你有两个嵌套的while循环,外面的是一个无限循环,正如你已经猜到的,这是阻塞主线程,因为你的代码永远不会退出。因此,没有其他代码可以执行,这可能会导致任何变化,甚至UI冻结。
由于在执行外循环时不会发生任何变化,因此内循环中的条件也不会改变,因此内循环也是无限的。
要实现这一点,实际上必须让代码执行结束,以便事件循环可以继续,更改可以发生,然后必须再次调用代码以评估新状态。
其次,list(和unchangedList)是函数参数,因此scoped locally to the function无法从函数外部更改它们的值,更改它们的代码必须驻留在函数/同一作用域中。
为了让事件循环继续,你需要结束你的代码执行,并将下一次执行的代码排队。例如,你可以使用setInterval

let list;
let unchangedList;

// initialize `list` here

// some example on how `list` could be updated
button.addEventListener('click', () => {
  // update `list`
});

function autoUpdate() {
  if (list !== unchangedList) {
    render(list);
    unchangedList = list;
  }
}

setInterval(autoUpdate, 0);

使用0 ms的时间间隔意味着“立即”执行回调,但仍然是异步的,也就是说,只是将其放入队列并继续执行。这允许事件循环执行其他队列回调(如果有的话)。
与其一直执行回调函数,不如使用requestAnimationFrame来减轻CPU负担。这样只会在绘制新帧之前将回调函数排队,这样效率更高,因为使用setInterval可以在绘制到屏幕之前多次重新渲染:

function autoUpdate() {
  if (list !== unchangedList) {
    render(list);
    unchangedList = list;
  }

  requestAnimationFrame(autoUpdate);
}
requestAnimationFrame(autoUpdate);

更有效的方法是只在实际发生更改时才调用代码,根据更改的来源,可以使用适当的事件侦听器(如input元素的change event或按钮和链接的click event)来完成此操作:

inputElement.addEventListener('change', () => render(inputElement.value));
buttonElement.addEventListener('click', () => {
  let list = getUpdatedList();
  render(list);
});

如果你想观察你的代码变量的变化,你可以使用可观察变量,比如RxJS

相关问题