JavaScript 学习笔记 - Web Workers

前言

本文仅是 Web Workers 的入门科普文章,不涉及太琐碎的知识点。javascript

咱们知道,在 Web Workers 出来以前,JavaScript 是单线程的。即便是 setTimeout 之类的看似多线程的函数,实际上也是单线程执行的。css

有时,咱们须要在浏览器执行一个比较耗时的计算:html

function count() {
    let i = 0
    let sum = 0

    for (let j = 0; j < 100; j++) {
        for (let i = 0; i < 100000000; i++) {
            sum += i
        }
    }

    return sum
}

若是直接在浏览器执行这段代码,会把浏览器卡死。对于这类耗时的计算,能够经过多线程来解决。java

多线程的重要性不言而喻。而工做线程(Web Workers),就是 JavaScript 的多线程解决方案。web

建立工做线程

建立工做线程很简单,只要新建一个 Worker 对象就能够了。api

css-demo/web-worker.html跨域

let worker = new Worker('worker.js')

这段代码建立了一个工做线程,用来执行 worker.js 的代码。咱们能够在 worker.js 执行比较耗时的计算。浏览器

咱们能够写一个简单的工做线程代码:安全

css-dmeo/worker.js服务器

console.log('hello world')

运行 css-demo/web-worker.html,能够看到控制台输出:

Failed to construct 'Worker': Script at 'file://xxx/javascript-demo/worker.js' cannot be accessed from origin 'null'

这是由于跨域的缘由,致使代码执行失败。咱们能够建立一个服务器环境(推荐 Http-server)来打开 HTML。

能够看到控制台输出:

hello world。

线程间消息传递

一般咱们在工做线程完成计算后,须要将计算结果传回给主线程。咱们能够经过 postMessage 方法把数据传给主线程。

web-worker-message.js

postMessage('hello world')

主线程注册 onmessage 回调函数,经过 event.data 接收工做线程传递过来的数据。

web-worker-message.html

let worker = new Worker('web-worker-message.js')
// 设置回调函数,接收 worker 传递过来的数据
worker.onmessage = function(event) {
    console.log(event.data)
}

执行后,控制台输出:

hello world

固然,咱们也能够传递其余类型的数据。好比,要传递多个数据时,能够先构造个对象,再传递过去。

postMessage({
    data1: 'hello',
    data2: 'world'
})

API 介绍

postMessage

postMessage(data, origin):工做线程向主线程传递数据,data 是传递的数据,origin 用来设置跨域相关的东西,这里不作介绍。

terminate

terminate() 函数用来结束工做线程。

web-worker-terminate.html

let worker = new Worker('web-worker-terminate.js')
worker.terminate()

web-worker-terminate.js

setTimeout(function () {
    console.log('hello')
}, 1000)

运行后,等了会儿,和预期的同样,控制台没有任何输出。

onmessage

onmessage:用来接收工做线程传递给主线程的消息。

onerror

onerror 用来处理线程错误。

web-worker-onerror.html

let worker = new Worker('web-worker-onerror.js')
worker.onerror = function(e) {
    // 打印错误消息
    console.log(e.message)
}

web-worker-onerror.js

undefinedFunction()

控制台输出:

Uncaught ReferenceError: undefinedFunction is not defined

除了普通的异常错误,404 等 HTTP 请求错误时也能回调。

let worker = new Worker('no-exist-url.js')
worker.onerror = function(e) {
    // 打印错误消息
    console.log(e.message)
}

控制台输出:

undefined

工做线程上下文

若是你试过在工做线程中执行 alert 函数,就会执行出错。

Uncaught ReferenceError: alert is not defined

这是由于在工做线程中,JavaScript 代码执行的上下文(Runtime Context)并非 Window 对象。

你能够在工做线程中执行:console.log(Window),控制台会输出:

Uncaught ReferenceError: Window is not defined

咱们能够经过 console.log(this) 把工做线程中当前上下文对象打印出来。

输出的不是 Window 对象。因为上下文的不一样,工做线程的 JavaScript API 会和之前的用法有点不同。最大的区别在于:工做线程中不能操做 DOM。

工做线程的职责在于处理数据,而后把处理完成的数据传给主线程,主线程再根据数据更新界面。

可能有人以为这样很麻烦,若是你作过多线程界面开发(好比 Android),应该清楚这样作的缘由:在多个线程同时更新 UI 的很不安全的。

总结

知识点很少,对于通常的使用,应该足够了。

相关文章
相关标签/搜索