Node.js TypeScript #12. Introduction to Worker Threads with TypeScript

JavaScript Node.js

This entry is part 13 of 15 in the Node.js TypeScript

The Node.js and JavaScript are often perceived as a single-threaded but in this series, we prove that it is not entirely true. Node.js creates threads when performing Input/Output operations. Not only that, but we can also create additional processes. While the above does not count yet as multithreading, in this article we begin to cover the basics of TypeScript Worker Threads and explore how they work and compare them to other ways of running JavaScript in parallel that we’ve used so far.

Introduction to TypeScript Worker Threads

First, let’s look into why would we want another way of running multiple pieces of code at once. In the 10th part of this series, we cover the child process module. It allows us to create additional Node.js processes with all its advantages and disadvantages. Since child processes don’t share any memory, every one of them needs to manage their own environment to run Node.js code. Not only it uses quite a bit of memory: it also takes some time to get it to run. Threads, compared to multiple processes, are lighter when it comes to resources.

TypeScript support in Worker Threads

Even though the Worker Threads module is relatively new, it has solid TypeScript support when it comes to types. When we look into the DefinitelyTyped repository, all the use cases that we need in this article are covered. Moreover, in the history of the typings, you can see that they receive updates along with new versions of Node.js. It is very important because the Worker Threads module is still in the experimental stage. It means that it is still in active development and therefore its API can still change. The Node.js team seems to put quite a focus on Worker Threads though and lately, Node.js changelog often mentions Worker Threads. Before, we needed to run Node with an additional flag,  , but not anymore.

With the  , we create a Worker in a similar way that we create a child process.

The only issue that we encounter is the lack of support for   files. When using the child process module, the new process inherits the   property and therefore it runs with TypeScript. Currently, it is not the case with Worker Threads. Trying to run a   file in a worker thread results in error:

The worker script extension must be “.js” or “.mjs”. Received “.ts”

As of now, the only way to overcome this issue is to import   files. There are a few approaches that we can take with this problem, for example creating a   file for every worker that we want to use as suggested on GitHub:

worker.js

Thanks to using  , the   file is compiled to TypeScript.

The above means quite a lot of redundant code because we need to create an additional    file for every worker. We can improve by passing a file name to the   file using  .

Communicating between threads

We can use the   parameter to send data to the newly created worker. It can be any value that can be cloned by the structured clone algorithm – the workers receive cloned value. The above puts a few constraints on what we pass as the  . For example, we can’t pass functions to it. Let’s use it to give the path of our  file to .

main.ts

When you are inside of a worker, you can read the  by importing it from the Worker Threads module. Let’s use it to resolve our   file.

worker.js

Thanks to the code above we have just one   file that imports any   file so that we can use TypeScript with Worker Threads easily.

Since we got that down, let’s implement a way for the main thread and our worker thread to communicate further.

Communicating with the parent thread

The easiest way to communicate the worker thread with the main thread is to use   that can be imported inside of a worker. You can send any data as long as it is compatible with the HTML structured clone algorithm.

worker.ts

In the code above we use the   function to send data back to the main thread. A way to receive it is to listen for the message event:

main.ts

1307674368000

And thanks to the code above we have our main thread communicating with the worker that is written in TypeScript!

Summary

In this article, we’ve covered the very basics of using TypeScript Worker Threads. To do this, we first had to figure out how to make them work with TypeScript. We also used the   to communicate our worker thread with the main thread, therefore making our code fully functional. In the upcoming article, we dive deeper into this topic by creating our own ports using the MessageChannel and share the data between threads.

Series Navigation<< Node.js TypeScript #15. Benefits of the HTTP/2 protocolNode.js TypeScript #13. Sending data between Worker Threads >>
Subscribe
Notify of
guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Rohit Gupta
Rohit Gupta
3 years ago

Inspiration from issues in https://github.com/TypeStrong/ts-node/issues/846

Last edited 3 years ago by Rohit Gupta