Javascript并发控制

时间:2011-09-07 18:24:17

标签: javascript concurrency

作为一个教育项目,我在JavaScript中编写(又一个)编辑风格的实时语法荧光笔。

为了让编辑器保持响应,我显然选择让荧光笔异步运行,但是对于我正在使用的模型我需要能够在启动另一个之前终止一个荧光笔,如果在当前荧光笔完成之前键入了某些内容,并且知道它在新的开始之前终止。

我在考虑做以下事情:

var terminate = false;
var terminated = false;

function work() {
  while(!terminate)
    console.log('working');
  terminated = true;
}

function stop() {
  terminate = true;
  while(!terminated);
  console.log('stopped');
}

setTimeout(work, 0);
setTimeout(stop, 10);

然而,这个例子不起作用,我尝试使用更多的setTimeouts代替繁忙的等待无济于事。

有没有办法在JavaScript中实现这样的系统,还是应该使用其他替代方法(或两者)?

2 个答案:

答案 0 :(得分:8)

如果你可以在没有DOM访问权限的情况下完成大部分工作,那么对于网络工作者来说这将是完美的。

要修复您的示例,请尝试使用setTimeout0进行控制。这有效:

var terminate = false;
var terminated = false;

function work() {
  if(!terminate) {
    console.log('working');
    setTimeout(work, 0);
  }
  else terminated = true;

}

function stop() {
  terminate = true;
  if(!terminated) {
      setTimeout(stop,0);
  }
  else console.log('stopped');
}

setTimeout(work, 0);
setTimeout(stop, 100);

修改

解释原始代码段的问题:Javascript是单线程的(除非您使用的是Web worker)。您可以使用事件,回调和setTimeout来实现并发的错觉,但您真正要做的是告诉运行时在将来某个时间执行您的回调函数。在您的情况下,stop永远不会被执行。 10 ms过期后,计划运行“下一步”(即work完成后。由于work从未完成,stop永远无法运行。

因此,您希望从javascript中获得的任何明显的并发性都将是合作的。你的工作者线程必须暂停并明确允许“其他东西”发生以保持幻觉。

答案 1 :(得分:2)

在这种情况下,请考虑使用Workers。大多数现代浏览器都支持它们。没有工人,javascript中没有真正的可靠性(这很好) - 所有都是在一个线程中完成的。

很多setTimeout()电话是杀手锏。