As the title says...
Basically, if I have a single webworker and post it 1000 messages at once.
Each message results in the worker performing a processing intensive operation.
Am I best to post each message to the webworker sequentially after the previous one completes, or can I safely send all the requests over to the worker knowing that they will just be processed and returned one by one as they complete?
If I do this am I better off implementing a queueing system within the worker? or is it not necessary?
I understand that this single worker is only a single thread and therefore the javascript operations will indeed occur synchronously within the webworker itself, but I am concerned about contention in a similar way that performing 200 ajax requests at once would overwhelm a browser.
I hope this makes.
The worker will queue up messages (specifically, it will queue up calls to onmessage
) and process each message when ever the worker's call stack is empty.
This means, however, that asynchronous operation could result in input multiple messages being processed before any any particular operation is completed. For example:
onmessage = function(e) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/" + e.data);
xhr.onload = function() {
postMessage(xhr.responseText);
}
}
If you passed in 1000 messages at once, I suspect the browser will fire off 1000 Ajax requests (or at least a lot of requests) before it runs postMessage
inside of onload
. This is because onload
does not run until the Ajax call is complete, and each onload
call will be added to the event queue behind any pending calls to onmessage
that were requested before the Ajax fetch could complete.
If you wanted to ensure that only one Ajax request is out at a time, you could indeed implement an internal queue that moved only when onload
was called:
var queue = [];
var busy = false;
onmessage = function(e) {
if(busy) {
queue.push(e);
}
else {
busy = true;
runAjax(e);
}
}
var runAjax = function(e) {
var xhr = new XMLHttpRequest();
xhr.open("GET", e.data);
xhr.onload = function() {
postMessage(xhr.responseText);
if(queue.length) {
// run the next queued item
runAjax(queue.shift());
} else {
busy = false;
}
}
}
In this case, the first messages goes into the else
block, which sets busy = true
and runs the Ajax fetch. The following 999 messages are routed to the if
block, because busy
is true
(and will not become false
until the Ajax request completed and queue
is empty). The queued messages are handled only after an Ajax request is complete.
If you wanted to tolerate more than one Ajax request at the time, you could use a counter instead of boolean: use busy++
and busy--
instead of setting true
and false
, and test that the current number of outstanding connections has not reached your allowed max (i.e., if(busy == 5)
instead of if(busy)
).