'How to post a message from a web worker to another web worker Javascript
I am trying to send a message from one worker to the other (and then respond back through a SharedArrayBuffer). But I can't find any information on posting a message to another worker from within a worker. How would I go about doing it? (I tried posting the worker itself as a message, but it doesn't work).
Here is my code:
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<script type='text/javascript'>
var s_curFile;
var s_curFile2;
var s_SAB = new SharedArrayBuffer(65563);
var u8buf = new Uint8Array(s_SAB);
function JSprocessFilePicker( input )
{
let url = input.value;
let ext = url.substring( url.lastIndexOf( '.' ) + 1 ).toLowerCase();
if ( input.files && input.files[0] && ( ext == "txt" ) )
{
s_curFile = input.files[0];
try {
fileWorker.postMessage({
'cmd' : 'file',
'file' : s_curFile
});
} catch(e) {
alert('Can\'t spawn files to worker - '+e)
}
try {
worker.postMessage({
'cmd' : 'run'
});
} catch(e) {
alert('Can\'t spawn files to worker - '+e)
}
}
}
u8buf[0] = 0;
var worker = new Worker('worker.js');
var fileWorker = new Worker('fileWorker.js');
try {
worker.postMessage({
'cmd' : 'SAB',
'sab' : s_SAB
}, fileWorker);
} catch(e) {
alert('Can\'t send Shared Array Buffer to worker - '+e);
}
try {
fileWorker.postMessage({
'cmd' : 'SAB',
'sab' : s_SAB
});
} catch(e) {
alert('Can\'t send Shared Array Buffer to worker - '+e);
}
var input = document.createElement( "input" );
input.setAttribute( "id", "file_picker" );
input.setAttribute( "type", "file" );
input.setAttribute( "accept", ".fzp" );
input.setAttribute( "onchange", "JSprocessFilePicker(this)" );
</script>
<button onclick="input.click();">Open</button>
</body>
</html>
worker.js:
var s_SAB;
var u8buf;
var fileWorker;
self.onmessage = function(e) {
if( e.data.cmd === 'SAB' )
{
s_SAB = e.data.sab;
u8buf = new Uint8Array(s_SAB);
fileWorker = e.data.fileWorker;
console.log(s_SAB);
console.log(fileWorker);
}
else if( e.data.cmd === 'run' )
{
try {
fileWorker.postMessage({
'cmd' : 'load'
});
} catch(e) {
console.log('Can\'t post message from web worker - '+e); //I GET AN ERROR HERE
}
while(u8buf[0] === 0)
{
//This loop here I am doing heavy processing, that i cannot change really
console.log("worker waiting for file...\n");
}
console.log("worker got data!\n");
let Idx;
for (Idx = 0; Idx < 20; ++Idx) {
console.log(u8buf[Idx+1]);
}
}
fileWorker.js
var s_curFile;
var s_SAB;
var u8buf;
let xhrReq = new XMLHttpRequest();
xhrReq.overrideMimeType('text/plain; charset=x-user-defined');
self.onmessage = function(e) {
if( e.data.cmd === 'file' )
{
s_curFile = e.data.file;
console.log("got file!");
}
else if( e.data.cmd === 'SAB' )
{
s_SAB = e.data.sab;
u8buf = new Uint8Array(s_SAB);
console.log(s_SAB);
}
else if( e.data.cmd === 'load' )
{
let uri = URL.createObjectURL(s_curFile.slice(40, 100));
xhrReq.open('GET', uri, true);
xhrReq.send(null);
URL.revokeObjectURL(uri);
let Idx;
let sz = xhrReq.response.length;
console.log("Response Size: "+sz);
for (Idx = 0; Idx < sz; ++Idx) {
u8buf[Idx+1] = xhrReq.response.charCodeAt(Idx);
}
u8buf[0] = 1;
}
}
Solution 1:[1]
TL;DR Do you really want to do this?
In order to even have access to a SharedArrayBuffer you have to set some specific headers to meet the post-Spectre security requirements. You can use Atomics.wait* to block a worker thread on change to a shared buffer to communicate from one worker to another if you really want...
Alternatively:
You could simply forward messages from one worker to the main thread using a simple postMessage to other workers, a very basic pub-sub if you will. Much easier to pull off.
* Only works with an Int32Array as the underlying buffer, not Uint8Array like you have in your example.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jared Smith |
