怎么在web worker启动的js线程调用native.js

JavaScript036

怎么在web worker启动的js线程调用native.js,第1张

HTML5-Web Workers实现多线程:

当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。虽然在JavaScript中有setInterval和setTimeout函数使javaScript看起来好像使多线程执行,单实际上JavaScript使单线程的,一次只能做一件事情。

可以运行以下示例,检验js的单线程特性。

相关代码请到github查看。

<div id='container'></div>

<script>

window.alert('hi')

setTimeout(function(){

var ul = document.createElement('ul')

var li = document.createElement('li')

var text = document.createTextNode('world')

var container = document.getElementById('container')

li.appendChild(text)

ul.appendChild(li)

container.appendChild(ul)

console.log('done!')

},2000)

</script>123456789101112131415123456789101112131415

如果JavaScript是多线程,在弹出警告框两秒后,页面应该出现一个li标签(内容为world)。事实上因为JavaScript是单线程,所以如果你不点击弹出框的确定按钮,world这个li永远也出不来。

点击确定后

web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行。

我们需要把希望单独执行的javascript代码放到一个单独的js文件中,然后在页面中调用Worker构造函数来创建一个线程,参数是该文件路径,参数存放如果是相对地址,那么要以包含调用Worker构造函数语句所在脚本为参照,如果是绝对路径,需要保证同源(协议+主机+端口)。这个文件不需要我们在页面使用script标签显示引用。

var worker = new Worker('src/js/worker.js')11

我们可以看到worker对象只有两个属性,其实是两个回调函数句柄

onerror:当worker运行出现错误,并且没有在worker中ing捕获,会在此捕获

onmessage:当worker向主线程发送消息是调用

在其prototype内有两个重要方法

postMessage:很熟悉的赶脚,之前我们介绍过window对象的postMessage()方法,woker的postMessage方法和window的比较类似,但参数略有不同,只需要传递消息内容就可以,而且支持所有JavaScript原生数据类型,当然不放心的话同样也可以序列化为字符串传递

terminate:终止worker执行,有些worker执行比较慢,主线程可以主动终止其执行

下面我们用web workers重写上面那个例子。

相关代码请到github查看。

test_web_worker.html

<script>

var worker = new Worker('./worker.js')

window.alert('hi')

</script>12341234

worker.js

setTimeout(function(){console.log('done!')},2000)

创建一个Worker

通常,与web worker相关的代码都放在一个独立的JavaScript文件中。父线程通过在Worker构造函数中指定一个JavaScript文件的链接来创建一个新的worker,它会异步加载并执行这个JavaScript文件。

var primeWorker = new Worker('prime.js')

启动Worker

要启动一个Worker,则父线程向worker传递一个信息,如下所示:

var current = $('#prime').attr('value')

primeWorker.postMessage(current)

父页面可以通过postMessage接口与worker进行通信,这也是跨源通信(cross-origin messaging)的一种方式。通过postMessage接口除了可以向worker传递私有数据类型,它还支持JSON数据结构。但是,你不能传递函数,因为函数也许会包含对潜在DOM的引用。

“父线程和worker线程有它们各自的独立空间,信息主要是来回交换而不是共享。”

信息在后台运行时,先在worker端序列化,然后在接收端反序列化。鉴于此,不推荐向worker发送大量的数据。

父线程同样可以声明一个回调函数,来侦听worker完成任务后发回的消息。这样,父线程就可以在worker完成任务后采取些必要的行动,比如更新DOM元素。如下代码所示:

primeWorker.addEventListener('message', function(event){

console.log('Receiving from Worker: '+event.data)

$('#prime').html( event.data )

})

event对象包含两个重要属性:

target:用来指向发送信息的worker,在多元worker环境下比较有用。

data:由worker发回给父线程的数据。

worker本身是包含在prime.js文件中的,它同时侦听message事件,从父线程中接收信息。它同样通过postMessage接口与父线程进行通信。

self.addEventListener('message', function(event){

var currPrime = event.data, nextPrime

setInterval( function(){

nextPrime = getNextPrime(currPrime)

postMessage(nextPrime)

currPrime = nextPrime

}, 500)

})

在本文例子中,我们寻找下一个最大的质数,然后不断将结果发回至父线程,同时不断更新界面以显示新的值。在worker的代码中,字段self和this都是指向全局作用域。Worker既可以添加事件侦听器来侦听message事件,也可以定义一个onmessage处理器,来接收从父线程发回的消息。

寻找下一个质数的例子显然不是worker的理想用例,但是在此选用这个例子是为了说明消息传递的原理。之后,我们会挖掘些可以通过web worker获得益处的实际用例。