Web Workers를 사용하면 웹 사용자 인터페이스를 차단하지 않고 백그라운드에서 JavaScript 코드를 실행할 수 있습니다. 웹 작업자는 웹 페이지의 전반적인 성능을 향상시키고 사용자 경험도 향상시킬 수 있습니다. Web Worker는 전용 Web Worker와 공유 Web Worker의 두 가지 형태로 제공됩니다. 이 기사에서는 애플리케이션에서 웹 워커를 사용하기로 결정하는 데 도움이 되기 위해 알아야 할 웹 워커의 7가지 주요 측면에 대해 설명합니다.
일반적으로 웹 페이지에 작성하는 JavaScript 코드는 사용자 인터페이스와 동일한 스레드에서 실행됩니다. 이것이 긴 프로세스를 트리거하는 버튼을 클릭하면 웹 페이지의 사용자 인터페이스가 정지되는 이유입니다. 처리가 완료될 때까지 사용자 인터페이스에서 작업할 수 없습니다. 웹 작업자를 사용하면 일부 스크립트가 동시에 실행되는 경우에도 사용자 인터페이스가 계속 응답하도록 백그라운드에서 JavaScript를 실행할 수 있습니다. 스크립트를 실행하는 백그라운드 스레드를 작업자 스레드 또는 작업자라고 부르는 경우가 많습니다. 원하는 만큼 많은 작업자를 생성할 수 있습니다. 작업자 스레드에서 실행 중인 스크립트에 데이터를 전달하고 완료되면 기본 스레드에 값을 반환할 수도 있습니다. 그러나 Web Workers에는 다음과 같은 몇 가지 제한 사항이 있습니다.
웹 작업자는 웹 페이지에서 DOM 요소에 액세스할 수 없습니다.
웹 작업자는 웹 페이지에서 전역 변수 및 JavaScript 함수에 액세스할 수 없습니다.
웹 작업자는 Alert() 또는 verify() 함수를 호출할 수 없습니다.
Web Worker에서는 창, 문서, 상위 개체와 같은 개체에 접근할 수 없습니다.
단, setTimeout(), setInterval() 등의 함수를 사용할 수 있습니다. XMLHttpRequest 객체를 사용하여 서버에 Ajax 요청을 할 수도 있습니다.
웹 작업자에는 전용 웹 작업자와 공유 웹 작업자라는 두 가지 유형이 있습니다. 전용 웹 작업자는 자신을 생성하는 웹 페이지와 함께 살고 죽습니다. 즉, 웹 페이지 내에서 생성된 전용 웹 작업자는 여러 웹 페이지에서 액세스할 수 없습니다. 반면에 공유 웹 작업자는 여러 웹 페이지에서 공유됩니다. Worker 클래스는 전용 웹 작업자를 나타내고, SharedWorker 클래스는 공유 웹 작업자를 나타냅니다.
대부분의 경우 전담 웹 작업자가 귀하의 요구 사항을 충족할 것입니다. 이는 일반적으로 작업자 스레드에서 웹 페이지에 대한 특정 스크립트를 실행해야 하기 때문입니다. 그러나 때로는 여러 웹 페이지에 공통적인 작업자 스레드에서 스크립트를 실행해야 하는 경우도 있습니다. 이 경우 각 페이지마다 하나씩 많은 전용 웹 작업자를 만드는 대신 공유 웹 작업자를 사용할 수도 있습니다. 한 웹 페이지에서 생성된 공유 웹 작업자는 다른 웹 페이지에서 계속 사용될 수 있습니다. 모든 연결이 닫혀 있는 경우에만 파괴될 수 있습니다. 공유 웹 작업자는 전용 웹 작업자보다 조금 더 복잡합니다.
이제 Web Worker의 기본 사항을 이해했으므로 전용 Web Worker를 사용하는 방법을 살펴보겠습니다. 아래에 설명된 예제에서는 즐겨 사용하는 개발 도구를 사용하여 웹 애플리케이션을 만들고 해당 스크립트 폴더에 jQuery 및 Modernizr 라이브러리도 추가했다고 가정합니다. 웹 애플리케이션에 HTML 페이지를 추가하고 다음 코드를 입력합니다.
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script src="scripts/modernizr.js"></script> <script src="scripts/jquery-2.0.0.js"></script> <script type="text/javascript"> $(document).ready(function () { if (!Modernizr.webworkers) { alert("This browser doesn't support Web Workers!"); return; } $("#btnStart").click(function () { var worker = new Worker("scripts/lengthytask.js"); worker.addEventListener("message", function (evt) { alert(evt.data); },false); worker.postMessage(10000); }); }); </script> </head> <body> <form> <input type="button" id="btnStart" value="Start Processing" /> </form> </body> </html>
위의 HTML 페이지에는 일부 JavaScript 처리를 트리거하는 버튼(btnStart)이 포함되어 있습니다. 이 페이지는 Modernizr 및 jQuery 라이브러리를 참조합니다. 3f1c4e4b6b16bbbd69b2ee476dc4f83a 블록에는 Ready() 메서드 핸들러가 포함되어 있으며 이 핸들러는 차례로 btnStart의 클릭 이벤트를 처리합니다. Ready() 핸들러는 먼저 브라우저가 웹 워커를 지원하는지 확인합니다. 이는 Modernizr의 webworkers 속성을 사용하여 수행됩니다. 브라우저가 웹 작업자를 지원하지 않으면 사용자에게 오류 메시지가 표시됩니다.
그런 다음 코드는 btnStart의 클릭 이벤트 핸들러에 연결됩니다. 클릭 이벤트 핸들러의 코드는 Worker 객체를 사용하여 백그라운드에서 스크립트를 실행하므로 중요합니다. click 이벤트 핸들러는 Worker 객체를 생성하고 이를 로컬 변수(worker)에 저장합니다. 백그라운드에서 실행될 JavaScript 파일의 경로가 생성자에 전달됩니다. 곧 LengthyTask.js를 생성하게 될 것입니다. 그런 다음 코드는 Worker 객체의 메시지 이벤트에 대한 이벤트 핸들러를 추가합니다. 메시지 이벤트는 대상 스크립트(이 경우 LongthyTask.js)가 일부 값을 웹 페이지로 다시 보낼 때 발생합니다. 메시지 이벤트 핸들러는 evt.data 속성을 사용하여 반환된 값에 액세스할 수 있습니다. 마지막으로 Worker 객체에서 postMessage() 메서드가 호출되어 LengthyTask.js 실행을 트리거합니다. postMessage() 메소드를 사용하면 대상 스크립트에 데이터를 전달할 수도 있습니다. 이 예에서는 처리가 지속되어야 하는 밀리초 수를 나타내는 숫자(10000)가 postMessage()에 전달됩니다. postMessage() 호출에서 JavaScript 객체나 문자열과 같은 다른 데이터를 전달할 수 있습니다.
LengthyTask.js 파일에는 아래와 같이 백그라운드에서 실행될 코드가 포함되어 있습니다.
addEventListener("message", function (evt) { var date = new Date(); var currentDate = null; do { currentDate = new Date(); } while (currentDate - date < evt.data); postMessage(currentDate); }, false);
上面的代码处理worker thread的消息事件。当主页面调用Worker对象上的postMessage()方法时,会引发消息事件。消息事件处理程序通过运行某些毫秒的do-while循环来模拟冗长的处理。此循环运行的毫秒数从主页传递(回忆前面讨论的postMessage())。因此,evt.data在此示例中返回10000。一旦长时间操作完成,代码调用postMessage()会把处理结果发送回主页面。在本例中,传递currentDate的值(currentDate是一个Date对象)。
如果你运行主网页并单击Start Processing按钮,那么你将在10秒后收到alert()。同时,页面的用户界面不会被阻止,你可以执行诸如滚动,点击等操作,表明来自LengthyTask.js的代码正在后台运行。
前面的示例使用了专用Web worker。让我们将同样的示例转换为使用共享Web worker。共享Web worker由SharedWorker对象表示。下面的代码显示了来自主页的代码的修改版本:
$(document).ready(function () { if (!Modernizr.webworkers) { alert("This browser doesn't support Web Workers!"); return; } $("#btnStart").click(function () { var worker = new SharedWorker("scripts/sharedlengthytask.js"); worker.port.addEventListener("message", function (evt) { alert(evt.data); }, false); worker.port.start(); worker.port.postMessage(10000); }); });
注意用粗体字标记的代码。它创建了一个SharedWorker实例,并在构造函数中传递SharedLengthyTask.js。你将很快创建此文件。然后,代码将消息事件处理程序连接到SharedWorker对象的端口对象。消息处理程序函数执行与前面示例中相同的工作。然后代码在端口对象上调用start()方法。最后,在端口对象上调用postMessage()方法将数据(10000)发送到共享worker thread。
SharedLengthyTask.js文件包含以下代码:
var port; addEventListener("connect", function (evt) { port = evt.ports[0]; port.addEventListener("message", function (evt) { var date = new Date(); var currentDate = null; do { currentDate = new Date(); } while (currentDate - date < evt.data); port.postMessage(currentDate); }, false); port.start(); }, false);
代码首先声明一个名为port的变量,用于存储端口对象的引用。这次处理了两个事件——connect和message。当与共享Web worker建立连接时,会触发connect事件。 connect事件处理程序捕获evt.port [0]对象并将其存储在之前声明的端口变量中。然后在端口对象上连接消息事件处理程序。调用端口对象的start()方法来开始侦听该端口上的消息。消息事件处理程序几乎与你在前面的示例中编写的消息事件处理程序相同,除了它附加到端口对象这一点。此外,在端口对象上调用postMessage(),以将处理结果发送到主页面。
有时Web Worker可能需要与Web服务器通信。例如,你可能需要驻留在某些RDBMS中的数据以便于客户端处理。要完成此类任务,你可以使用XMLHttpRequest对象向服务器端资源发出请求。实例化Worker对象和处理消息事件的整个过程保持不变。但是,你需要向服务器端资源发出GET或POST请求。考虑下面的代码:
addEventListener("message", function (evt) { var xhr = new XMLHttpRequest(); xhr.open("GET", "lengthytaskhandler.ashx"); xhr.onload = function () { postMessage(xhr.responseText); }; xhr.send(); }, false);
上面显示的代码创建了XMLHttpRequest对象的实例。然后调用open()方法,并指定向服务器端资源LengthyTaskHandler.ashx(一个ASP.NET通用处理程序)发出GET请求。(虽然此示例使用ASP.NET通用处理程序,但你可以使用任何其他服务器端资源。)然后它处理XMLHttpRequest对象的load事件并调用postMessage()。 xhr.responseText作为postMessage()的参数。xhr.responseText将是ASP.NET通用处理程序作为响应返回的值。请求完成时引发load事件。
LengthyTaskHandler.ashx包含以下代码:
namespace WebWorkersDemo { public class LengthyTaskHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { System.Threading.Thread.Sleep(10000); context.Response.ContentType = "text/plain"; context.Response.Write("Processing successful!"); } public bool IsReusable { get { return false; } } } }
正如你可以看到,ProcessRequest()通过在Thread类上调用Sleep()方法来模拟一些冗长的处理,并阻止执行10秒。然后它返回一个成功消息“Processing successful!”给调用者。如果你在进行这些更改后运行主网页,你会发现在10秒后,将显示一个包含此成功消息的警报对话框。
如果你的Web worker正在进行一些复杂的操作,那么你可能需要添加错误处理到主网页代码,以便在worker中出现任何未处理错误时,可以采取适当的操作。这可以通过处理Worker对象的错误事件来完成。每当work thread中存在任何未处理的错误时,就会抛出错误事件。以下代码显示了如何完成此操作:
$("#btnStart").click(function () { var worker = new Worker("scripts/lengthytask.js"); worker.addEventListener("message", function (evt) { alert(evt.data); }, false); worker.addEventListener("error", function (evt) { alert("Line #" + evt.lineno + " - " + evt.message + " in " + evt.filename); }, false); worker.postMessage(10000); });
从上面的代码可以看出,错误处理程序已经连接到worker对象的错误事件。错误处理函数接收一个事件对象,而该对象提供错误信息,例如发生错误的行号(evt.lineno),错误消息(evt.message)和发生错误的文件(evt.filename)。
때로는 워커에서 실행 중인 작업을 취소하고 싶을 수도 있습니다. 이를 위해 종료() 메서드를 호출하여 작업자를 삭제할 수 있습니다. 작업자가 종료되면 재사용하거나 다시 시작할 수 없습니다. 물론 언제든지 다른 Worker 인스턴스를 생성하여 사용할 수 있습니다. 그러나 Terminate()는 작업자를 즉시 종료하고 정리 작업을 수행할 기회를 제공하지 않는다는 점을 기억하십시오.
웹 작업자를 사용하면 웹 사용자 인터페이스를 정지하지 않고도 백그라운드에서 스크립트를 실행할 수 있습니다. 전용 웹 작업자와 공유 웹 작업자의 두 가지 유형이 있습니다. 각 웹페이지에 대한 전용 웹 작업자를 만들고, 공유 웹 작업자를 사용하여 여러 웹 페이지에서 공유하세요. Worker 클래스는 전용 웹 작업자를 나타내고 SharedWorker 클래스는 공유 웹 작업자를 나타냅니다. 이 기사에서는 두 가지 유형을 모두 사용하는 방법과 오류를 처리하는 방법 및 웹 작업자가 XMLHttpRequest를 사용하여 웹 서버와 통신하는 방법에 대해서도 설명합니다.
위 내용은 웹 작업자에 대해 알아야 할 7가지 사항의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!