带你了解Web Worker - 实操篇

1-Web Worker 实际操做步骤

Dedicated Worker

接下来咱们开始讲解一个使用 Web Worker 运算斐波那契数列的例子。项目地址javascript

首先,咱们须要经过Worker()构造器建立worker实例,其只接受一个参数,该参数则是线程脚本的地址,该地址必须符合同源策略。html

能够查看代码,我再使用同目录下的 dedicate-worker.js 文件建立了一个 Worker 对象出来,当初始化完成后,浏览器后台线程就回运行该脚本了。java

var worker = new Worker('dedicate-worker.js');
复制代码

那主线程(页面)和后台线程的 Worker 之间是如何通讯的呢?这里就要 postMessage 方法了。git

worker.postMessage(message, [transfer]);
复制代码

postMessage 方法接受两个参数,第一个就是 worker 之间传递的数据信息,第二个参数是一个数组,用来转让对象全部权。github

/* html 部分 <div class='normal'> <button onclick='normalPost(34)'>34</button> <button onclick='normalPost(42)'>42</button> </div> */
// js 部分
function normalPost(num) {
    worker.postMessage(num);
}
复制代码

上述代码中,当咱们点击对应的按钮时候,会发送数字到对应的到子线程。后台子进程须要监听 onmessage 事件,才能接受主进程发送来的数据。而该事件接受一个 MessageEvent 对象,其中 data 属性就是主进程传入的数据。web

// dedicate-worker.js
// 斐波那契数列
function fabonacci(n) {
    if (n === 0) {
        return 0;
    }
    if (n === 1) {
        return 1;
    }
    return fabonacci(n - 1) + fabonacci(n - 2);
}

onmessage = function(messageEvent) {
    var str = messageEvent.data;
    str = typeof str === 'number' ? String(str) : str;
    switch (str) {
	    // ...
        case (str.match(/[0-9]/) || {}).input:
            var result = fabonacci(Number(str));
            postMessage({msg: str+'的斐波那契数列是:' + result, code: 'fobo'});
            break;
        default:
            postMessage({msg: 'hi, bro~ 慢慢想一下~', code: ''});
            break;
    }
}
复制代码

上述代码中,咱们经过 onmessage 监听获取主线程传输进来的数据,若是对应的数据运算完成事后,直接调用 postMessage 方法将对应的结果传输出去,注意在子进程的脚本中,由于全局做用域已经改变的缘由是能够直接调用 postMessage 的方法,可是在主进程中是不能够的,是须要指定对应的wroker对象调用的。chrome

回到主进程代码,在这里咱们也只要让对应的 worker 监听 onmessage 事件便可接受由子线程传递过来的数据。数组

worker.addEventListener('message', (e) => {
    var res = e.data;
    switch (e.data.code) {
        default:
            app.textContent = res.msg;
            break;
    }
    // ...
});
复制代码

由于 Worker 仍是比较消耗资源的,因此当没有用的时候,能够选择关闭,即调用 terminate 方法便可。浏览器

var worker = new Worker('dedicate-worker.js');
worker.terminate();
复制代码

shared Worker

咱们实现一个多个 tab 共享部分数据效果。大概这样的效果: app

多个tab共享文字效果图

Shared Worker 建立的方法相似于 dedicated Worker,调用 SharedWorker 构造器,语法以下:

new SharedWorker(aURL, name);
复制代码

其中 aURL 表示脚本的地址,name 表示子线程的名字,同名的线程是能够共享的噢,但依旧要遵循同源策略。在咱们的项目中,咱们是这样建立的:

var shareWorker = new SharedWorker('share-worker.js', 'sharedWork');
复制代码

一样的咱们能够经过 postMessage 方法将信息传递给子进程,但由于 SharedWorker 实现的缘由不一样,咱们须要经过实例的 port 属性去调用 postMessage。

input.addEventListener('change', (e) => {
    shareWorker.port.postMessage({value: e.target.value, type: 'write'});
})
复制代码

上述代码中,咱们经过监听输入框的 change 事件触发主线程传递信息给子线程。而子线程由于做用域的不一样,对应的链接主线程方式稍有不一样,咱们经过监听 onconnect 接通主线程,而后经过接受参数的 ports 属性获取到 MessagePort 对象,这时候即可以使用 onmessage 和 postMessage 处理和传递数据了。

// ...
onconnect = function (messageEvent) { 
    messageEvent.source.addEventListener('message', (event) => {
            swicthByTypeCode(event.data);
    })
    source.start();
}
// ...
复制代码

上述代码,主要是子线程链接主线程,并让 MessagePort 对象监听 message 事件,但注意若使用 addEvevntListener 监听的时候,须要自行 start 方法启动。

调试

调试 Dedicated Worker 能够直接在控制台进行调试,惟独调试 SharedWorker 的时候须要进入 chrome://inspect/#workers 点开 inspect 进行调试。

对应的控制台展现以下:

看到了最熟悉的界面,就能够 debugger 调试了。上述仅仅描述了简单的用法,并没有涉及某些高级用法,如 importScripts 的应用、错误处理机制等。其实上文有不断的说起到 Worker 的做用域和 window 的做用域是不一样的,那接下来咱们看看他们究竟是什么样子哩?

相关文章
相关标签/搜索