Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run CPU intensive operations in worker thread in Angular 4 and updating progress in the UI?

I see a couple of examples that Jason Teplitz has written about using web workers in Angular 2. The Angular 4 CLI now supports platform-worker that runs the app in a worker thread. The factorial example is a good example of that. Or this step-by-step example.

  1. Using platform-worker guarantee that all the long computational operations run in a web worker? Or should I create another angular module (not the app module) which uses the platform-worker to run the long computation operation? As a result there will be two modules, one for the app and the other for the long operation?

  2. Should I create separate Worker like in this example to create worker threads?

  3. How can I update the UI with the progress of the operation? I assume if the long operation is done in a for loop, it wont get the chance to let the UI know about the progress until that loop is complete? Should I split the long operation into multiple small operations and update the UI?

like image 434
wonderful world Avatar asked Jul 05 '17 11:07

wonderful world


People also ask

What are Webworkers in angular?

Web workers lets you run CPU-intensive computations in a background thread, freeing the main thread to update the user interface.


1 Answers

I'll try to provide at least a placeholder answer, until we can get a more exhaustive one:

  1. Yes, platform-worker takes your code off of UI thread.

Longer explanation

Using platform-worker guarantees that your code is running in web worker. Angular still has to run some code on "this side" of things, on UI thread, but platform-worker basically moves all your code and logic into a worker thread, calculates all the DOM calls, and when the time is right, it calls your DOM with it's magic. But that is not the whole picture, so let's consider things a bit more.

  1. Separate worker: depends, but TL;DR: yes.

Longer explanation

Your question implies some heavy computation work. Not heavy UI work, but heavy computation work. This is different than just offloading all the UI work on the main thread.

If you have heavy app (like huge table with many bindings, or many components running a lot of CPU-heavy tasks), that might be considered heavy app. It definitely pays to offload it to worker. But if your app isn't that complex, and only certain work is, you might consider separating your app and your work. Even if you offload your app to a worker, if there is a task that kills the whole worker for a while, your whole app, UI and all, gets unresponsive for a while. Sure, you can scroll and click, but angular, since it is on the same thread as your long-running heavy synchronous task, has no chance to respond. So it's almost the same as if it was all running on the UI thread.

That's why I believe you can still create a separate Worker for your heavy task. You need to give Angular place to breathe, too.

  1. Can you do UI updates: depends.

Longer explanation

You also worry how will you update things in a for loop. Well, if you have a long-running synchronous task - then you need to provide updates inbetween the loop runs in that job runner.

Why? Because, if you cannot stop running (sync stuff), then angular will not have a chance to step out of your code (within web worker) and post a message to UI thread (and UI part of angular) and update the UI. Or if you have a separate worker job, it simply won't tell angular how far it has gone.

So, if your entire app is in the web worker (together with the heavy-CPU logic), you could, e.g. every 100 iterations, go update some local observable or similar, and set the next loop run to run later in a setTimeout. It should give Angular a chance to send the update of this obsevable value to the DOM renderer who in turn can notify the UI thread of the change.

And if your app is in a separate worker than your actual CPU-heavy task, then you still need to send this update every, say, 100 iterations, to your Angular app.

That way your Angular app is still responsive, and you can still have a service that listens to job progress updates from this worker and update the UI. (again, e.g. every 100 loop runs post a message to the other end of the worker). E.g. you just show a lil spinner somewhere, when the user clicks, it shows how far is the task, and the user can use other parts of the app.

If you provide more details about your intensive CPU task, maybe someone can provide a better answer. I hope this one helps clear things up a bit at least.

like image 132
Zlatko Avatar answered Oct 12 '22 00:10

Zlatko