Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bubble a web worker error in a promise via worker.onerror?

I'm dealing with a web worker that needs to report back if an error has occured. Normally, I can use worker.onerror to listen to any errors that were thrown from the worker. However, when the error happens in a promise in the web worker, I can't figure out how to bubble the error back up to worker.onerror.

Excuse the odd code snippet, as this seems to be the only way to demonstrate worker behavior. (The worker is defined in the HTML section).

function getInlineJS() {
  var js = document.querySelector('[type="javascript/worker"]').textContent;
  var blob = new Blob([js], {
    "type": "text\/plain"
  });
  return URL.createObjectURL(blob);
}

var worker = new Worker(getInlineJS());

worker.onerror = function(err) {
  document.getElementById('errors').innerHTML += 
    "error " + err.message + '\n';
}

worker.onmessage = function (msg) {
  console.log("message recieved", msg);
  document.getElementById('messages').innerHTML += 
    "message " + msg.data + '\n';
}


worker.postMessage("run");
worker.postMessage("promise");
should write "Normal Error and In Promise Error" below and in console (promise error only occurs in console though): <br>

<pre id="errors">
</pre>

messages:
<pre id="messages">
</pre>

<script type="javascript/worker">
self.addEventListener("message", function(e) {
    /* demonstration of normal error bubbling to onerror */
    if (e.data == 'run') {
      throw new Error('Normal Error');
      return;
    }
    new Promise(function(resolve, reject) {
      /* some logic that breaks */
      throw new Error('In Promise Error');
    }).then(function(result) {
      
    }).catch(function(err) {
      /* QUESTION: HOW TO GET THIS ERROR OUT OF WORKER? */
      
      /* it logs to console just fine */
      console.log("In Promise Catch Error:", err);
      
      /* postMessage doesn't work for some reason */
      self.postMessage({error: err});
      
      /* and this doesn't bubble it to worker.onerror */
      throw err; /* doesn't bubble!! */
    });
});
</script>

How can I retrieve web worker errors that happen inside promises?

like image 330
Tennyson H Avatar asked Oct 12 '16 07:10

Tennyson H


1 Answers

postMessage doesn't work for some reason

That's because you're returning an object instead of a string, change it to self.postMessage({error: err.message});

As for your second problem, you can use the setTimeout(function() { throw err; }); trick. More information about the situation and trick can be found here.

function getInlineJS() {
  var js = document.querySelector('[type="javascript/worker"]').textContent;
  var blob = new Blob([js], {
    "type": "text\/plain"
  });
  return URL.createObjectURL(blob);
}

var worker = new Worker(getInlineJS());

worker.onerror = function(err) {
  document.getElementById('errors').innerHTML += 
    "error " + err.message + '\n';
}

worker.onmessage = function (msg) {
  console.log("message recieved", msg);
  document.getElementById('messages').innerHTML += 
    "message " + msg.data + '\n';
}


worker.postMessage("run");
worker.postMessage("promise");
should write "Normal Error and In Promise Error" below and in console (promise error only occurs in console though): <br>

<pre id="errors">
</pre>

messages:
<pre id="messages">
</pre>

<script type="javascript/worker">
self.addEventListener("message", function(e) {
    /* demonstration of normal error bubbling to onerror */
    if (e.data == 'run') {
      throw new Error('Normal Error');
      return;
    }
    new Promise(function(resolve, reject) {
      /* some logic that breaks */
    
      throw new Error('In Promise Error');
    }).then(function(result) {
      
    }).catch(function(err) {
      /* it logs to console just fine */
      console.log("In Promise Catch Error:", err);
      
      /* postMessage works when you return a string. */
      self.postMessage({error: err.message});

       setTimeout(function() { throw err; }); 
    });
});
</script>
like image 188
Nick Avatar answered Nov 14 '22 23:11

Nick