是否可以"线程化"Javascript并保持对UI的访问?

TER*_*ytE 9 html javascript user-interface multithreading

我想在一些主要进程和线程可以自由更新浏览器UI的同时编写一些Javascript代码.

例如:

function StartStuff() {
    StartThreadedCode();
    // do more work and update the UI while StartThreadedCode() does its work
}

function StartThreadedCode() {
    // do stuff (do work and update the UI)
}
Run Code Online (Sandbox Code Playgroud)

可能吗?

zat*_*ata 17

在Javascript中实现"多线程"有两种主要方式.第一种方法是跨浏览器解决方案,它也适用于旧版浏览器,但实现起来更复杂.

它背后的想法是你给UI一些时间来每隔一段时间更新一次.由于Javascript中没有同步休眠函数,实现此目的的唯一方法是使用setTimeout(或具有更复杂逻辑的setInterval)来延迟复杂计算的每个循环的执行.这将为浏览器提供一些时间来更新循环之间的UI,从而同时发生多个事物的视觉效果.几毫秒应该足以让UI反映最新的变化.

它当然有它的缺点,并且如果在执行后台计算时用户可能想要做多个动作,则可能很难实现.它也可以大大减慢整个背景计算速度,因为它偶尔会延迟几毫秒.然而,在特定情况下,它可以完成并且表现良好.

第二种选择是使用web worker,它们基本上是在后台独立运行的Javascript脚本,就像一个线程.它实现起来要容易得多,您只需担心主代码和后台工作者之间的消息传递,因此您的整个应用程序不会受到太大影响.您可以在Mic https://developer.mozilla.org/en/Using_web_workers发布的链接中阅读有关使用它们的信息.网络工作者最大的缺点是他们的浏览器支持,你可以在http://caniuse.com/#search=worker上看到.对于IE <9或真正模拟效果的移动浏览器,没有可能的解决方法,因此没有多少你可以对这些浏览器做些什么,但是再一次,现代浏览器的好处可能会超过糟糕的IE支持.当然,这取决于您的申请.

编辑:我不确定我是否清楚地解释了第一个概念,所以我决定添加一个小例子.以下代码在功能上等同于:

for (var counter = 0; counter < 10; counter++) {
  console.log(counter);
}
Run Code Online (Sandbox Code Playgroud)

但是,不是快速连续记录0-9,而是在执行循环的下一次迭代之前延迟1秒.

var counter = 0;

// A single iteration of your calculation function
// log the current value of counter as an example
// then wait before doing the next iteration
function printCounter() {
  console.log(counter);
  counter++;
  if (counter < 10)
    setTimeout(printCounter, 1000);
}

// Start the loop
printCounter();
Run Code Online (Sandbox Code Playgroud)