HTML5标准与性能之一:WebWorkers

使用HTML5开发的应用越来越多,很多针对性能提升的新标准也开始逐渐提出,提交到HTML5、EcmaScript等标准中,给HTML5的应用更强大的计算能力。我们分4篇文章分别介绍一下这些针对HTML5性能的新标准:Web Workers, Typed Array, ParallelArray 和 asm.js。

之一:Web Workers

Web Workers是一个在前端实现多线程的JS接口,属于W3C的HTML5标准的一部分,现在大多数浏览器包括移动浏览器都支持Web Workers.

大家知道,JavaScript是一个单线程的语言,所有函数的执行实际上都是串行的。如果一个函数运行的时间过长,则会导致UI停止响应。而Web Workers可以创建一个独立的JS线程,在这个线程中的函数不会阻塞主线程(也称UI线程)的执行。如果在你的代码中有一些执行时间特别长的函数,主要是用来做复杂的数学计算而不是修改UI,就建议把函数放在Web Workers线程内执行。Web Workers也正是为这种场景来设计的,因为Web Worker拥有一个跟UI线程完全独立的环境,两者之间不共享任何内存变量Web Worker中不包含DOM树和CSS相关的API,主线程和Worker线程之间靠消息传递来实现变量的共享。

我们来看一个例子来简单了解一下Web Worker:

页面(main.html)

<div id="result"></div>
<div>
<span>No Web Workers: </span><button onclick="uiFib(10)">uiFib(10)</button><button onclick="uiFib(40)">uiFib(40)</button>
</div>
<div>
<span>Web Workers: </span><button onclick="workerFib(10)">workerFib(10)</button><button onclick="workerFib(40)">workerFib(40)</button>
</div>
<script src="main.js"></script>

主线程文件(main.js)

// Web Worker版本的函数调用
function workerFib(n) {
     var worker = new Worker('worker-thread.js'); // 使用独立的文件'worker-thread.js'创建Web Worker线程
     worker.onmessage = function (evt) { // 收到Worker发过来的消息
         document.getElementById('result').innerHTML = evt.data;
     };
    worker.postMessage(n); // 发送消息给Worker线程
}
// 在UI线程内的函数调用
function uiFib(n) {
    var ret = fib(n);
    document.getElementById('result').innerHTML = ret;
}
// 递归实现的斐波那契数列计算函数
function fib (n) {
    if (n < 0) return -1;
    else if (n === 0 || n === 1) {
        return 1;
    } else {
        return fib(n - 2) + fib(n - 1);
    }
}

Worker线程文件(worker-thread.js)


// 监听UI线程发过来的消息
onmessage = function (evt) {
    var n = evt.data;  // 获取数据作为参数
    var ret = fib (n);  // 计算
    postMessage(ret); // 将计算结果传递给UI线程
};
// 递归实现的斐波那契数列计算函数
function fib (n) {
    if (n < 0) return -1; // 非法参数返回-1
    else if (n === 0 || n === 1) {
        return 1;
    } else {
        return fib(n - 2) + fib(n - 1);
    }
}

通过浏览器打开main.html(由于安全限制需要通过HTTP服务器访问),点击uiFib(40)的按钮后你会发现UI线程被阻塞,导致整个界面在计算完成前不响应,而点击Web Worker版本的workerFib(40),由于在不同线程内执行,UI界面不会停止响应,点击其他按钮仍然有反应。

For more complete information about compiler optimizations, see our Optimization Notice.