In fact, a Web Worker is similar to a thread separate from the principal. However, it is completely isolated from both this and the DOM (i.e. the "View"), so that the only form of communication between him and the thread is through the use of postMessage
. In addition to DOM, it also does not have access to other features and global variables/functions/classes available to common scripts.
The main utility of a Web Worker is to separate into one thread/separate process any heavy/time-consuming processing that would otherwise completely block the page until it was completed. An example of use would be:
script_normal.js
// Cria o web worker
var worker = new Worker('web_worker.js');
// Diz o que fazer quando o web worker enviar uma mensagem
worker.addEventListener('message', function(e) {
var dados = e.data;
alert("O resultado é: " + dados.resultado);
});
// Manda uma mensagem pro web worker
worker.postMessage({ cmd:"acharPrimo", n:100 }); // assíncrono - retorna imediatamente
web_worker.js
// Diz o que fazer quando outro thread enviar uma mensagem
addEventListener('message', function(e) {
var dados = e.data;
if ( dados.cmd == "acharPrimo" ) {
var ret = acharPrimo(dados.n); // Chama uma função demorada
postMessage({ resultado:ret }); // Manda o resultado como mensagem
}
// Outras funções, se aplicável
});
function acharPrimo(n) {
// Acha o n-ésimo primo, construindo um crivo, etc...
}
That is, when the page starts the time-consuming process, it doesn’t "lock" until this process is ready - you can continue using it, in the same way you would if you had made an Ajax call to the server (except that in this case, everything is happening on its own browser). This process occurs in parallel and, when finished, sends the results to the page (in an event also asynchronous) that can then do something with it. Both the page and the worker can send multiple messages to each other - for example, to display a progress bar to the user.
A care that needs to be taken with its use is in sending messages: the thread main and the worker have separate address space (i.e. do not share memory). This means that all data passed from one to the other is serialized string before being sent. In the example shown, when passed:
{ cmd:"acharPrimo", n:100 }
pro worker, was not an object that was passed, but a string representing that object. In this case, the object was small, but if it were something very large (like an array with several elements) its copy from one to the other - by means of string representation, on top of that - could have a significant impact on performance. There is an alternative - not yet widely supported, at least last time I checked - that would be the use of transferables, objects whose "ownership" is transferred from a thread to another. That is, the same object that was once in one thread now happens to be in another, becoming inaccessible to the first, but without occurring any copy.
Another necessary care would be to remember that the web worker in itself is single-threaded, that is: after a lengthy process has begun, it has to go all the way before another begins. It can send messages to the thread main at will, but the reciprocal is not true: as long as this code does not finish executing, messages sent to worker will be lined up until it is available.
A corollary is that you can’t "kill" the process by sending a message from stop for him - because this message would only be received after the process has already ended... In such a case, it would be preferable that his worker only executed a single loop iteration at a time, pausing before executing the next one (giving time for pending messages to be processed). And of course, if you have two or more processing to do, or you create two Workers or ensures that one of them is idle before reusing it (a pool of Workers is better than always creating a new one, because it eliminates the overhead of creation).
Finally, it should be mentioned that a WebWorker
common is only accessible to thread that created it (whether the main, or other web worker), but it is possible to share a worker with others through the use of a SharedWorker
. Its functionality is quite similar to that of a worker common, but its API has some differences, especially in the form of a thread communicate with another.
Clear, concise and enlightening! Thank you! Just one more question, where can I find out from which versions browsers they support Web Worker?
– Jothaz
@Jay On MDN (compatibility table at the bottom of the page).
– bfavaretto
@Jota Conforme o caniuse with. all the browsers except IE9 or earlier give support.
SharedWorker
, on the other hand, only Chrome and Firefox. I have no information about transferables...– mgibsonbr
Thanks again for the clarifications.
– Jothaz