>  기사  >  웹 프론트엔드  >  웹 워커로 시작하기

웹 워커로 시작하기

WBOY
WBOY원래의
2023-09-04 12:49:011138검색

JavaScript 언어의 많은 디자인 목표 중 하나는 단일 스레드와 단순성을 유지하는 것입니다. 인정해야 하지만, 언어 구조의 특성을 고려하면 결코 간단하지 않습니다! 그러나 "단일 스레드"가 의미하는 것은 JavaScript에는 제어 스레드가 하나만 있다는 것입니다. 불행히도 JavaScript 엔진은 한 번에 한 가지 작업만 수행할 수 있습니다.

이것은 컴퓨터에서 유휴 멀티 코어 프로세서를 사용하는 데 너무 제한적으로 들리지 않습니까? HTML5는 모든 것을 바꿀 것을 약속합니다.


JavaScript를 위한 단일 스레드 모델

Web Worker는 DOM이 스레드로부터 안전하지 않기 때문에 DOM에 액세스할 수 없는 제한된 세계에 살고 있습니다.

JavaScript의 단일 스레드 특성을 단순화로 보는 학파도 있고, 한계로 보는 학파도 있습니다. 후자 그룹은 매우 좋은 점을 가지고 있습니다. 특히 현대 웹 애플리케이션은 UI 이벤트 처리, 서버측 API 쿼리 또는 폴링, 대량 데이터 처리, 서버 응답을 기반으로 DOM 조작을 위해 JavaScript를 많이 사용하기 때문에 더욱 그렇습니다. p>

반응형 UI를 유지하면서 단일 제어 스레드에서 너무 많은 작업을 수행할 수 있다는 것은 종종 어려운 작업이므로 개발자는 동시성을 달성하기 위해 해킹 및 해결 방법(예: setTimeout(), setInterval(),或者使用XMLHttpRequest 및 DOM 이벤트 사용)에 의존해야 합니다. 그러나 이러한 기술은 확실히 비동기적으로 호출하는 방법을 제공하지만 비차단이 반드시 동시를 의미하는 것은 아니라는 점은 주목할 가치가 있습니다. John Resig는 자신의 블로그에서 어떤 것도 병렬로 실행할 수 없는 이유를 설명합니다.

제한사항

오랜 기간 동안 JavaScript를 사용해 왔다면 특정 스크립트를 실행하는 데 시간이 너무 오래 걸린다는 내용의 다음과 같은 귀찮은 대화 상자를 접했을 가능성이 높습니다. 예, 페이지가 응답하지 않을 때마다 거의 대부분의 원인은 일부 JavaScript 코드 때문일 수 있습니다.

从 Web Worker 开始

스크립트를 실행하는 동안 브라우저가 중단될 수 있는 몇 가지 이유는 다음과 같습니다.

  • 과도한 DOM 작업: DOM 작업은 아마도 JavaScript에서 가장 비용이 많이 드는 작업일 것입니다. 따라서 많은 수의 DOM 조작 작업으로 인해 스크립트가 리팩토링에 적합한 후보가 됩니다.
  • 끝이 없는 루프: 코드에서 복잡한 중첩 루프를 검색해도 나쁠 것이 없습니다. 이들은 실제로 필요한 것보다 더 많은 작업을 수행하는 경향이 있습니다. 어쩌면 동일한 기능을 제공하는 다른 솔루션을 찾을 수도 있습니다.
  • 둘을 결합: 우리가 할 수 있는 최악의 일은 더 우아한 솔루션이 존재할 때(예: DocumentFragment 사용) 루프에서 DOM을 반복적으로 업데이트하는 것입니다.

네트워크 직원이 구조하러 옵니다

...비차단이 반드시 동시를 의미하는 것은 아닙니다...

HTML5 및 Web Workers 덕분에 이제 새로운 스레드를 생성하여 진정한 비동기성을 제공할 수 있습니다. 작업자 스레드가 많은 양의 데이터를 처리하는 중이더라도 기본 스레드가 UI 이벤트를 처리하는 동안 새 작업자 스레드는 백그라운드에서 실행될 수 있습니다. 예를 들어 작업자는 대규모 JSON 구조를 처리하여 UI에 표시할 중요한 정보를 추출할 수 있습니다. 이제 장황한 이야기는 그만하고 실제 코드를 살펴보겠습니다.

직원 만들기

일반적으로 Web Worker와 관련된 코드는 별도의 JavaScript 파일에 있습니다. 상위 스레드는 JavaScript 파일을 비동기적으로 로드하고 실행하는 Worker 생성자에 스크립트 파일의 URI를 지정하여 새 작업자를 생성합니다.

으아악

작업자 스레드 시작

작업 스레드를 시작하기 위해 상위 스레드는 다음과 같이 작업자 스레드에 메시지를 보냅니다.

으아악

상위 페이지에서는 postMessage API 与工作人员通信,该 API 也用于跨源消息传递。除了向工作程序发送原始数据类型之外,postMessage API를 사용할 수 있으며 JSON 구조 전달도 지원합니다. 그러나 기본 DOM에 대한 참조가 포함될 수 있으므로 함수를 전달할 수 없습니다.

상위 스레드와 작업자 스레드는 각자의 독립된 공간을 가지며, 주고받는 메시지는 공유되지 않고 복사됩니다.

내부적으로 이러한 메시지는 작업자 스레드에서 직렬화된 다음 수신 측에서 역직렬화됩니다. 따라서 작업자 스레드에 대량의 데이터를 보내는 것은 권장되지 않습니다.

상위 스레드는 작업을 수행한 후 작업자 스레드가 다시 보낸 모든 메시지를 수신하기 위해 콜백을 등록할 수도 있습니다. 이를 통해 작업자 스레드가 작업을 완료한 후 상위 스레드가 필요한 작업(예: DOM 업데이트)을 수행할 수 있습니다. 이 코드를 살펴보세요:

으아악

event 객체에는 두 가지 중요한 속성이 포함되어 있습니다.

  • <code><b>target</b>target
  • : 메시지를 보내는 작업자를 식별하는 데 사용되며 주로 다중 작업자 환경에서 유용합니다.
  • <b>data</b>
  • data
: 작업자가 상위 스레드로 다시 보내는 메시지입니다.

prime.js 中,并注册从其父级接收的 message 事件。它还使用相同的 postMessage

worker 자체는 🎜 API에 포함되어 상위 스레드와 통신합니다. 🎜
self.addEventListener('message',  function(event){
    var currPrime = event.data, nextPrime;
    setInterval( function(){

    nextPrime = getNextPrime(currPrime);
    postMessage(nextPrime);	
    currPrime = nextPrime;

    }, 500);
});

网络工作者生活在一个受限且线程安全的环境中。

在此示例中,我们只需找到下一个最大素数,然后重复将结果发送回父线程,父线程又用新值更新 UI。在工作者上下文中, selfthis 均指全局范围。 Worker 可以为 message 事件添加事件侦听器,也可以定义 onmessage 处理程序来侦听父线程发送的任何消息。

查找下一个素数的任务显然不是工作人员的理想用例,但在这里选择它是为了演示传递消息的概念。随后,我们确实探索了使用 Web Worker 真正能带来好处的可能且实际的用例。

终止员工

工人是资源密集型的;它们是操作系统级线程。因此,您不想创建大量工作线程,并且应该在 Web Worker 完成工作后终止它。工人可以终止自己,如下所示:

self.close();

或者父线程可以终止工作线程:

primeWorker.terminate();

安全和限制

在工作脚本中,我们无法访问许多重要的 JavaScript 对象,例如 documentwindowconsoleparent,最重要的是无法访问 DOM。没有 DOM 访问权限并且无法更新页面确实听起来限制太多,但这是一个重要的安全设计决策。想象一下,如果多个线程尝试更新同一元素,可能会造成严重破坏。因此,网络工作者生活在一个受限且线程安全的环境中。

话虽如此,您仍然可以使用worker来处理数据并将结果返回到主线程,然后主线程可以更新DOM。尽管他们被拒绝访问一些非常重要的 JavaScript 对象,但工作人员可以使用一些函数,例如 setTimeout()/clearTimeout()setInterval()/clearInterval()navigator 等。还可以在工作器内使用 XMLHttpRequestlocalStorage 对象。

同源限制

在工作者上下文中, selfthis 均指全局范围。

为了与服务器通信,工作人员必须遵循同源策略。例如,托管在 http://www.example.com/ 上的脚本无法访问 https://www.example.com/ 上的脚本。即使主机名相同,同源策略也规定协议也必须相同。通常,这不是问题。您很可能正在编写工作程序、客户端,并从同一域为它们提供服务,但了解限制总是有用的。

Google Chrome 的本地访问问题

Google Chrome 对本地访问工作程序设置了限制,因此您将无法在本地设置上运行这些示例。如果您想使用 Chrome,则必须在某个服务器上托管这些文件,或者在从命令行启动 Chrome 时使用 --allow-file-access-from-files 标志。对于 OS X,按如下方式启动 chrome:

$ /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --allow-file-access-from-files

但是,不建议在生产环境中使用此标志。因此,最好的选择是将这些文件托管在网络服务器上,并在任何支持的浏览器中测试您的网络工作人员。

调试 Worker 和错误处理

无法访问 console 使得这有点不简单,但是借助 Chrome 开发工具,人们可以像调试任何其他 JavaScript 代码一样调试工作代码。

从 Web Worker 开始

要处理 Web Worker 抛出的任何错误,您可以侦听 error 事件,该事件会填充 ErrorEvent 对象。您可以检查该对象以了解错误的详细原因。

primeWorker.addEventListener('error', function(error){
    console.log(' Error Caused by worker: '+error.filename
        + ' at line number: '+error.lineno
        + ' Detailed Message: '+error.message);
});

多个工作线程

虽然多个工作线程在它们之间划分工作是很常见的,但需要注意的是。官方规范指定这些工作人员相对重量级,预计将是在后台运行的长期脚本。 Web Worker 不适合大量使用,因为它们的启动性能成本和每个实例的内存成本都很高。

共享工作人员简介

该规范概述了两种类型的工作人员:专用工作人员和共享工作人员。到目前为止,我们已经看到了敬业工人的例子。它们直接链接到其创建者脚本/页面,因为它们与创建它们的脚本/页面具有一对一的关系。另一方面,共享工作人员可以在同一个来源的所有页面之间共享(即:同一来源的所有页面或脚本都可以与共享工作人员通信)。

要创建共享工作线程,只需将脚本的 URL 或工作线程的名称传递给 SharedWorker 构造函数即可。

共享工作程序使用方式的主要区别在于,它们与 port 相关联,以跟踪访问它们的父脚本。

以下代码片段创建一个共享工作线程,注册回调以监听该工作线程发布的任何消息,并将消息发布到共享工作线程:

var sharedWorker = new SharedWorker('findPrime.js');
sharedWorker.port.onmessage = function(event){
    ...
}

sharedWorker.port.postMessage('data you want to send');

类似地,工作人员可以侦听 connect 事件,当新客户端尝试连接到工作人员时会收到该事件,然后相应地向其发送消息。

onconnect = function(event) {
    // event.source contains the reference to the client's port
    var clientPort = event.source;
    // listen for any messages send my this client
    clientPort.onmessage = function(event) {
        // event.data contains the message send by client
        var data = event.data;
        ....
        // Post Data after processing
        clientPort.postMessage('processed data');
    }
};

由于它们的共享性质,您可以在同一应用程序的不同选项卡中维护相同的状态,因为不同选项卡中的两个页面使用相同的共享工作脚本来维护和报告状态。有关共享工作人员的更多详细信息,我鼓励您阅读规范。


实际用例

Web Worker 不适合大量使用,因为它们的启动性能成本很高,每个实例的内存成本也很高。

现实生活中的场景可能是,您被迫处理同步第三方 API,该 API 强制主线程在继续执行下一条语句之前等待结果。在这种情况下,您可以将此任务委托给新生成的工作线程,以利用异步功能为您带来好处。

Web 工作人员还擅长轮询情况,在这种情况下,您可以在后台连续轮询目标,并在一些新数据到达时将消息发布到主线程。

您可能还需要处理服务器返回的大量数据。传统上,处理大量数据会对应用程序的响应能力产生负面影响,从而使用户体验变得不可接受。更优雅的解决方案是将处理工作分配给多个工作人员来处理数据的非重叠部分。

其他用例可能是在多个网络工作人员的帮助下分析视频或音频源,每个工作人员都处理问题的预定义部分。


结论

想象一下在单线程环境中与多个线程相关的强大功能。

与 HTML5 规范中的许多内容一样,Web Worker 规范也在不断发展。如果您打算成为网络工作者,那么看看规范不会有什么坏处。

对于使用当前版本的 Chrome、Safari 和 Firefox 的专业工作人员来说,跨浏览器支持相当不错。即使是 IE 也没有落后太多,IE10 占据了主导地位。但是,仅当前版本的 Chrome 和 Safari 支持共享工作线程。令人惊讶的是,Android 4.0 中提供的最新版本的 Android 浏览器不支持 Web Worker,尽管在 2.1 版本中支持了 Web Worker。 Apple 还从 iOS 5.0 开始提供了 Web Worker 支持。

想象一下在单线程环境中与多线程相关的强大功能。可能性是无限的!

위 내용은 웹 워커로 시작하기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.