Sam*_*ler 105
有关最新的支持信息,请访问http://caniuse.com/#search=worker.
以下是大约2009年的支持状况.
你想谷歌的词是JavaScript工作者线程
除了Gears之外,目前还没有什么可用,但是有很多关于如何实现这一点的讨论,所以我想看看这个问题,因为答案无疑会在未来发生变化.
以下是Gears:WorkerPool API的相关文档
WHATWG有一份关于工作者线程的建议草案:Web Workers
还有Mozilla的DOM Worker Threads
更新: 2009年6月,当前浏览器支持JavaScript线程的状态
Firefox 3.5有网络工作者.一些网络工作者的演示,如果你想看到他们的行动:
Gears插件也可以安装在Firefox中.
Safari 4和WebKit nightlies都有工作线程:
Chrome有Gears,所以它可以做线程,虽然它需要用户的确认提示(它使用不同的API到Web工作者,虽然它可以在安装了Gears插件的任何浏览器中工作):
IE8和IE9只能安装Gears插件的线程
Lud*_*ltz 67
在HTML5之前,JavaScript只允许每页执行一个线程.
有以模拟与异步执行一些哈克的方式产率,setTimeout(),setInterval(),XMLHttpRequest或事件处理程序(看到此信息的用于与例如端部收率和setTimeout()).
但是使用HTML5,我们现在可以使用工作线程来并行执行函数.这是一个使用示例.
HTML5引入了Web Worker Threads(请参阅:浏览器兼容性)
注意:IE9及更早版本不支持它.
这些工作线程是在后台运行的JavaScript线程,不会影响页面的性能.有关Web Worker的 更多信息,请阅读文档或本教程.
下面是一个简单的示例,其中3个Web Worker线程计数到MAX_VALUE并在页面中显示当前计算的值:
//As a worker normally take another JavaScript file to execute we convert the function in an URL: http://stackoverflow.com/a/16799132/2576706
function getScriptPath(foo){ return window.URL.createObjectURL(new Blob([foo.toString().match(/^\s*function\s*\(\s*\)\s*\{(([\s\S](?!\}$))*[\s\S])/)[1]],{type:'text/javascript'})); }
var MAX_VALUE = 10000;
/*
* Here are the workers
*/
//Worker 1
var worker1 = new Worker(getScriptPath(function(){
self.addEventListener('message', function(e) {
var value = 0;
while(value <= e.data){
self.postMessage(value);
value++;
}
}, false);
}));
//We add a listener to the worker to get the response and show it in the page
worker1.addEventListener('message', function(e) {
document.getElementById("result1").innerHTML = e.data;
}, false);
//Worker 2
var worker2 = new Worker(getScriptPath(function(){
self.addEventListener('message', function(e) {
var value = 0;
while(value <= e.data){
self.postMessage(value);
value++;
}
}, false);
}));
worker2.addEventListener('message', function(e) {
document.getElementById("result2").innerHTML = e.data;
}, false);
//Worker 3
var worker3 = new Worker(getScriptPath(function(){
self.addEventListener('message', function(e) {
var value = 0;
while(value <= e.data){
self.postMessage(value);
value++;
}
}, false);
}));
worker3.addEventListener('message', function(e) {
document.getElementById("result3").innerHTML = e.data;
}, false);
// Start and send data to our worker.
worker1.postMessage(MAX_VALUE);
worker2.postMessage(MAX_VALUE);
worker3.postMessage(MAX_VALUE);Run Code Online (Sandbox Code Playgroud)
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>Run Code Online (Sandbox Code Playgroud)
我们可以看到三个线程以并发方式执行,并在页面中打印它们的当前值.它们不会冻结页面,因为它们是在后台以分离的线程执行的.
实现此目的的另一种方法是使用多个iframe,每个iframe将执行一个线程.我们可以通过URL 为iframe提供一些参数,iframe可以与其父级进行通信,以获得结果并将其打印回来(iframe必须位于同一个域中).
此示例不适用于所有浏览器! iframe通常在与主页面相同的线程/进程中运行(但Firefox和Chromium似乎以不同方式处理它).
由于代码段不支持多个HTML文件,因此我将在此处提供不同的代码:
index.html的:
//The 3 iframes containing the code (take the thread id in param)
<iframe id="threadFrame1" src="thread.html?id=1"></iframe>
<iframe id="threadFrame2" src="thread.html?id=2"></iframe>
<iframe id="threadFrame3" src="thread.html?id=3"></iframe>
//Divs that shows the result
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
<script>
//This function is called by each iframe
function threadResult(threadId, result) {
document.getElementById("result" + threadId).innerHTML = result;
}
</script>
Run Code Online (Sandbox Code Playgroud)
thread.html:
//Get the parameters in the URL: http://stackoverflow.com/a/1099670/2576706
function getQueryParams(paramName) {
var qs = document.location.search.split('+').join(' ');
var params = {}, tokens, re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params[paramName];
}
//The thread code (get the id from the URL, we can pass other parameters as needed)
var MAX_VALUE = 100000;
(function thread() {
var threadId = getQueryParams('id');
for(var i=0; i<MAX_VALUE; i++){
parent.threadResult(threadId, i);
}
})();
Run Code Online (Sandbox Code Playgroud)
'天真'的方式是setTimeout()一个接一个地执行这个功能:
setTimeout(function(){ /* Some tasks */ }, 0);
setTimeout(function(){ /* Some tasks */ }, 0);
[...]
Run Code Online (Sandbox Code Playgroud)
但是这种方法不起作用,因为每个任务将一个接一个地执行.
我们可以通过递归调用函数来模拟异步执行,如下所示:
var MAX_VALUE = 10000;
function thread1(value, maxValue){
var me = this;
document.getElementById("result1").innerHTML = value;
value++;
//Continue execution
if(value<=maxValue)
setTimeout(function () { me.thread1(value, maxValue); }, 0);
}
function thread2(value, maxValue){
var me = this;
document.getElementById("result2").innerHTML = value;
value++;
if(value<=maxValue)
setTimeout(function () { me.thread2(value, maxValue); }, 0);
}
function thread3(value, maxValue){
var me = this;
document.getElementById("result3").innerHTML = value;
value++;
if(value<=maxValue)
setTimeout(function () { me.thread3(value, maxValue); }, 0);
}
thread1(0, MAX_VALUE);
thread2(0, MAX_VALUE);
thread3(0, MAX_VALUE);Run Code Online (Sandbox Code Playgroud)
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>Run Code Online (Sandbox Code Playgroud)
正如您所看到的,第二种方法非常慢并冻结浏览器,因为它使用主线程来执行这些功能.
产量是一个新功能的ECMAScript 6,它仅适用于Firefox和Chrome的旧版本(在Chrome中,你需要启用实验性JavaScript出现在镀铬://标志/#启用JavaScript的-和谐).
yield关键字导致生成器函数执行暂停,yield关键字后面的表达式值返回给生成器的调用者.它可以被认为是return关键字的基于生成器的版本.
生成器允许您暂停执行函数并在以后恢复它.可以使用生成器通过称为trampolining的技术来安排您的功能.
这是一个例子:
var MAX_VALUE = 10000;
Scheduler = {
_tasks: [],
add: function(func){
this._tasks.push(func);
},
start: function(){
var tasks = this._tasks;
var length = tasks.length;
while(length>0){
for(var i=0; i<length; i++){
var res = tasks[i].next();
if(res.done){
tasks.splice(i, 1);
length--;
i--;
}
}
}
}
}
function* updateUI(threadID, maxValue) {
var value = 0;
while(value<=maxValue){
yield document.getElementById("result" + threadID).innerHTML = value;
value++;
}
}
Scheduler.add(updateUI(1, MAX_VALUE));
Scheduler.add(updateUI(2, MAX_VALUE));
Scheduler.add(updateUI(3, MAX_VALUE));
Scheduler.start()Run Code Online (Sandbox Code Playgroud)
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>Run Code Online (Sandbox Code Playgroud)
这里只是一种在Javascript中模拟多线程的方法
现在我将创建3个线程,它们将计算数字加法,数字可以除以13,数字可以除以3到10000000000.这三个函数不能像Concurrency那样同时运行.但是我将向您展示一个技巧,使这些函数在同一时间递归运行:jsFiddle
这段代码属于我.
身体的一部分
<div class="div1">
<input type="button" value="start/stop" onclick="_thread1.control ? _thread1.stop() : _thread1.start();" /><span>Counting summation of numbers till 10000000000</span> = <span id="1">0</span>
</div>
<div class="div2">
<input type="button" value="start/stop" onclick="_thread2.control ? _thread2.stop() : _thread2.start();" /><span>Counting numbers can be divided with 13 till 10000000000</span> = <span id="2">0</span>
</div>
<div class="div3">
<input type="button" value="start/stop" onclick="_thread3.control ? _thread3.stop() : _thread3.start();" /><span>Counting numbers can be divided with 3 till 10000000000</span> = <span id="3">0</span>
</div>
Run Code Online (Sandbox Code Playgroud)
Javascript部分
var _thread1 = {//This is my thread as object
control: false,//this is my control that will be used for start stop
value: 0, //stores my result
current: 0, //stores current number
func: function () { //this is my func that will run
if (this.control) { // checking for control to run
if (this.current < 10000000000) {
this.value += this.current;
document.getElementById("1").innerHTML = this.value;
this.current++;
}
}
setTimeout(function () { // And here is the trick! setTimeout is a king that will help us simulate threading in javascript
_thread1.func(); //You cannot use this.func() just try to call with your object name
}, 0);
},
start: function () {
this.control = true; //start function
},
stop: function () {
this.control = false; //stop function
},
init: function () {
setTimeout(function () {
_thread1.func(); // the first call of our thread
}, 0)
}
};
var _thread2 = {
control: false,
value: 0,
current: 0,
func: function () {
if (this.control) {
if (this.current % 13 == 0) {
this.value++;
}
this.current++;
document.getElementById("2").innerHTML = this.value;
}
setTimeout(function () {
_thread2.func();
}, 0);
},
start: function () {
this.control = true;
},
stop: function () {
this.control = false;
},
init: function () {
setTimeout(function () {
_thread2.func();
}, 0)
}
};
var _thread3 = {
control: false,
value: 0,
current: 0,
func: function () {
if (this.control) {
if (this.current % 3 == 0) {
this.value++;
}
this.current++;
document.getElementById("3").innerHTML = this.value;
}
setTimeout(function () {
_thread3.func();
}, 0);
},
start: function () {
this.control = true;
},
stop: function () {
this.control = false;
},
init: function () {
setTimeout(function () {
_thread3.func();
}, 0)
}
};
_thread1.init();
_thread2.init();
_thread3.init();
Run Code Online (Sandbox Code Playgroud)
我希望这种方式会有所帮助.
您可以使用Narrative JavaScript,一种将您的代码转换为状态机的编译器,有效地允许您模拟线程.它通过在允许您在单个线性代码块中编写异步代码的语言添加"让步"运算符(标记为" - >")来实现.
| 归档时间: |
|
| 查看次数: |
120345 次 |
| 最近记录: |