我想在主进程和线程都可以自由更新浏览器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)
}
有可能吗?
答案 0 :(得分: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);
}
但是不是快速连续记录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();
答案 1 :(得分:1)
截至2009年(FF 3.5 / Gecko 1.9.1),添加了一个名为Web Workers的新Web API。它也适用于Chrome 4 +,Opera 10.6+和IE10 +。
worker基本上是一个后台线程,它在一个单独的进程中运行。
主进程(例如你的UI的主线程)和从进程(后台线程,worker)之间的通信是借助于通用的PostMessage / onmessage函数建立的,你可以在它之间交换你喜欢的任何数据。双方。
值得一提的是,每个工作人员都被分配到不同的核心。例如,通过在四处理器上创建4个不同的工作程序(执行长时间计算),您将看到所有4个CPU核心,如100%,而主脚本仍处于空闲状态,从而响应您的UI事件(看this example)。
一个基本的例子:
主要-的script.js 强>
if ("function" !== typeof window.Worker) {
throw "Your browser doesn't support Web Workers";
}
var thread = new Worker("background-thread.js");
thread.onmessage = function(e) {
console.log("[A] : I received a " + e.data + " :-P");
};
thread.onerror = function(e) {
console.log(e);
};
console.log("[A] : I'm sending a PING :-)");
thread.postMessage("PING");
<强>背景thread.js 强>
onmessage = function(e) {
console.log("[B] : I receveid a " + e.data + " :-)");
console.log("[B] : I will respond with a PONG ;-)");
postMessage("PONG");
};
以上示例应在浏览器的控制台上生成以下输出:
[A]:我正在发送PING: - )
[B]:我收到一个PING: - )
[B]:我将以PONG回应; - )
[A]:我收到了PONG :-P
很高兴你的背景脚本!
答案 2 :(得分:0)