web workers_如何使用Web Workers在JavaScript中安排一致的异步任务

web workers

by Danny Mcwaves

丹尼·麦克维斯(Danny Mcwaves)

如何使用Web Workers在JavaScript中安排一致的异步任务 (How to use Web Workers to schedule consistent asynchronous tasks in JavaScript)

With the continuous improvements being made to Javascript engines, and the ever-expanding list of deprecated and new API’s to the ECMASCRIPT specification, the quest for blazing fast web applications has never been more on the rise.

随着Javascript引擎的不断改进,以及针对ECMASCRIPT规范的不推荐使用的新API列表的不断扩大,对快速Web应用程序的追求从未像现在这样Swift增长。

什么是Javascript引擎? (What is the Javascript Engine?)

The Javascript engine is a virtual machine. A virtual machine refers to the software-driven emulation of a given computer system. The basic job of a Javascript engine is to take the Javascript code that a developer writes and convert it to fast, optimized code that can be interpreted by a browser.

Javascript引擎是虚拟机。 virtual machine是指给定计算机系统的软件驱动的仿真。 Javascript引擎的基本工作是获取开发人员编写的Javascript代码,并将其转换为浏览器可以解释的快速优化代码。

Usually, this process runs on a single thread (more on threads later), with each statement of the developer’s code executed one at a time. The problem with single-threaded applications/architecture is that if any statement or block of statements takes a long time to complete, all subsequent statements hang up until that statement/block of statements finishes. This is known as BLOCKING. To avoid blocking, a program has to be multi-threaded.

通常,此过程在单个线程上运行(稍后将在更多线程上运行),并且每次执行开发人员代码的每个语句一次。 单线程应用程序/体系结构的问题在于,如果任何语句或语句块需要很长时间才能完成,则所有后续语句都将挂断,直到该语句/语句块完成为止。 这称为“ BLOCKING 。 为了避免阻塞,程序必须是多线程的。

穿线 (Threading)

A thread is an execution context, which is all the information a CPU needs to execute a stream of instructions.

线程是执行上下文,它是CPU执行指令流所需的所有信息。

Suppose you’re reading a book, and you want to take a break right now, but you want to be able to come back and resume reading from the exact point where you stopped. One way to achieve that is by jotting down the page number, line number, and word number. So your execution context for reading a book is these three numbers.

假设您正在读书,现在想休息一下,但是您希望能够回来并从停下的确切位置继续阅读。 实现此目的的一种方法是记下页码,行号和单词号。 因此,您阅读本书的执行上下文是这三个数字。

If you have a roommate, and she’s using the same technique, she can take the book while you’re not using it, and resume reading from where she stopped. Then you can take it back, and resume it from where you were.

如果您有一个室友,并且她正在使用相同的技术,则可以在不使用它时拿起这本书,然后从停下来的地方继续阅读。 然后,您可以将其取回,并从您所在的位置恢复。

Threads work in the same way. A CPU is giving you the illusion that it’s doing multiple computations at the same time. It does that by spending a bit of time on each computation. It can do that because it has an execution context for each computation.

线程以相同的方式工作。 CPU给您一种错觉,即它同时进行多个计算。 它通过在每次计算上花费一些时间来做到这一点。 之所以能够做到这一点,是因为它具有每次计算的执行上下文。

Just like you can share a book with your friend, many tasks can share a CPU. This process is called multi-threading and it solves BLOCKING. To support multi-threading on the frontend, web workers were created.

就像您可以与朋友共享一本书一样,许多任务可以共享一个CPU。 这个过程称为多线程,它解决了BLOCKING 。 为了在前端支持多线程,创建了Web worker。

网络工作者 (Web Workers)

The simplest use of workers is for performing a computationally expensive task without interrupting the user interface. (Source)

worker的最简单用法是执行计算量大的任务,而不会中断用户界面。 ( 来源 )

Web workers enable multi-threading on the front end by spawning new background threads and running scripts in isolation. As a result, scripts executed by workers need to be contained in separate files. Because web workers execute scripts in isolated threads, scripts do not interfere with the main thread and consequently do not interrupt the UI.

Web Worker通过生成新的后台线程并隔离运行脚本来在前端启用多线程。 结果,工作人员执行的脚本需要包含在单独的文件中。 因为Web工作人员在隔离的线程中执行脚本,所以脚本不会干扰主线程,因此不会中断UI。

创建一个Web Worker (Creating a Web Worker)

For didactic purposes, the excerpted script below is to be run in a separate thread.

出于教学目的,下面摘录的脚本将在单独的线程中运行。

### fetch.js

self.addEventListener(‘message’,  e => {
    let url = e.data;
    
    fetch(url).then(res => {
        if (res.ok) {
            self.postMessage(res);
        } else {
            throw new Error(’error with server’);
        }
    }).catch(err => {
        self.postMessage(err.message);
    });
})

The Worker() constructor call creates a worker and returns a Worker object representing that worker, which is used to communicate with the worker.

Worker()构造函数调用创建一个工作程序,并返回一个代表该工作程序的Worker对象,该对象用于与该工作程序进行通信。

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

The constructor takes the name of the script as an argument. If the specified file exists, the worker spawns a new thread and then completely downloads and executes the script. If the file is unavailable, the worker fails silently.

构造函数将脚本名称作为参数。 如果指定的文件存在,则工作程序会产生一个新线程,然后完全下载并执行脚本。 如果文件不可用,则工作器将静默失败。

使用网络工作者 (Using Web Workers)

Web workers communicate with the parent thread (the creator of the worker) using an event model and messages. It uses MessagePort objects behind the scenes, and thus supports all the same features, such as sending structured data and transferring binary data.

Web Worker使用事件模型和消息与父线程(Worker的创建者)进行通信。 它在后台使用MessagePort对象,因此支持所有相同的功能,例如发送结构化数据和传输二进制数据。

To receive messages from a worker, use the onmessage event handler on the Worker object.

要从工作程序接收消息,请在Worker对象上使用onmessage事件处理程序。

worker.onmessage = (e) => { // block statements }

You can also use the addEventListener method.

您也可以使用addEventListener方法。

worker.addEventListener('message', (e) => { // block statements })

To receive a message inside of the worker, the onmessage event handler method is used.

要在工作程序内部接收消息,请使用onmessage事件处理程序方法。

onmessage = (e) => { // blocks of statements }

You can also use an addEventListener method as exemplified in fetch.js.

您还可以使用fetch.js示例的addEventListener方法。

To send data to and from a worker, use the postMessage() method. Structured data such as text and JSON can be sent over this communication channel. Read more on data types that are supported by messagePort over here.

要向工作人员发送数据,请使用postMessage()方法。 可以通过此通信通道发送文本和JSON之类的结构化数据。 在此处详细了解messagePort支持的数据类型。

worker.postMessage('some-lousy-data');
// in the parent thread

self.postMessage('some-resulting-data');
// in the worker thread.

This particular message-passing limitation is in place for a number of reasons: it keeps the child worker running securely (since it can’t, blatantly, affect a parent script) and it keeps the parent page thread-safe (having the DOM be thread safe would be a logistical nightmare for browser developers).

这种特殊的消息传递限制是出于多种原因而存在的:它使子工作程序保持安全运行(因为它不能公然影响父脚本),并且使父页面保持线程安全(使DOM为对于浏览器开发人员来说,线程安全将是后勤上的噩梦)。

终止工作人员并处理错误 (Terminating a worker and handling errors)

If you need to immediately terminate a running worker from the main thread, you can do so by calling the worker’s terminate method:

如果您需要立即从主线程终止正在运行的工作程序,则可以通过调用工作程序的terminate方法来终止此工作:

worker.terminate();

In the worker thread, workers may close themselves by calling their own close method:

在worker线程中,worker可以通过调用自己的close方法来关闭自己:

close();

The worker thread is killed immediately without an opportunity to complete its operations or clean up after itself.

工作线程被立即杀死,而没有机会完成其操作或自行清理。

Runtime errors can be handled by explicitly listening for an error event that might be fired by the Worker object.

可以通过显式侦听Worker对象可能引发的错误事件来处理运行时错误。

worker.addEventListener('error', (e) => { // block of statements })
网络工作者的局限性 (Web Worker Limitations)
  1. All web worker scripts must be served from the same domain.

    所有Web Worker脚本必须从同一域提供。
  2. You cannot have direct access to the DOM and the global document.

    您不能直接访问DOM和全局文档。
  3. The window object exposes limited API. For instance, location and navigator and XMLHttpRequest objects.

    窗口对象公开了有限的API。 例如, locationnavigator以及XMLHttpRequest对象。

  4. Restricted local access. Web workers do not work on static files. For instance file://my/file/on/my/computer.

    本地访问受限。 Web Worker无法处理静态文件。 例如file://my/file/on/my/computer

If you are using a worker to handle a task that ultimately needs to update the main user interface, you will need to use the messaging system to pass the data between the worker and the main application. The main application is then responsible for updating the UI.

如果要使用工作程序来处理最终需要更新主用户界面的任务,则需要使用消息传递系统在工作程序和主应用程序之间传递数据。 然后,主应用程序负责更新UI。

Similarly, if your worker needs access to data from the document, window, or parent objects, you will need to send it in the postMessage() call that is used to start the worker.

同样,如果您的工作程序需要访问文档,窗口或父对象中的数据,则需要在用于启动工作程序的postMessage()调用中发送数据。

结论 (Conclusion)

Creating web workers will spawn real OS-level threads that consume system resources. Just be conscious that this will affect the performance of the user’s whole computer, not just the web browser. As such, web workers should be used responsibly and closed when they are no longer in use to free up resources for other applications.

创建Web Worker将产生消耗系统资源的实际OS级线程。 请注意,这将影响用户整个计算机的性能,而不仅仅是Web浏览器。 因此,应该负责任地使用Web Worker,并在不再使用Web Worker时释放它们以释放其他应用程序的资源。

Using web workers can have a significant impact on the performance of web applications; and more responsive applications have a good effect on user experience.

使用Web Worker会对Web应用程序的性能产生重大影响。 响应速度更快的应用程序对用户体验有很好的影响。

For a more in-depth information on web workers such as importing scripts in workers and the scopes of web workers, please visit MDN or WHATWG.

有关Web工作人员的更深入的信息,例如在工作人员中导入脚本以及Web工作人员的范围,请访问MDNWHATWG

For a fully functional example of web workers, visit here.

有关网络工作者的完整功能示例,请访问此处

翻译自: https://www.freecodecamp.org/news/how-web-workers-can-help-with-consistent-asynchronous-tasks-in-javascript-cd6d728fa4ee/

web workers

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值