[Noisebridge-discuss] Asynchronous Callbacks and Error Handling

Garrett Smith dhtmlkitchen at gmail.com
Sat Mar 29 22:16:39 UTC 2014


Async callbacks happen outside of the normal event loop.
http://jsbin.com/laraqozi/1/edit

The call to setTimeout in the try block succeeds without error,
passing it the function.

Later, when the browser calls the callback that was passed to
setTimeout, an error is thrown.

Similarly with event handler callbacks that throw errors, either from
IO or from something as simple as onclick:

  document.addEventListener("click", doSomethingBad, false);

No error is thrown by attaching `doSomethingBad`; the error happens
when doSomethingBad is triggered later on.

Asynchronous errors are harder to track down because the stack trace
stops at the browser internal code. The function that called
setTimeout is not part of the stack trace.

The contrived example is pretty obvious about what it does: throw
Error("..."). In reality, code that is throwing an error will be more
complicated and may depend the state of other objects. Conditional
breakpoints can help.

Async errors can't be caught in a sync try/catch, but can be caught by
either wrapping the call to the callback in a try/catch and handling
the error there, or by using a global onerror handler. But global
onerror won't tell you more than developer tools' stack trace does and
is only useful for graceful error-handling and reporting in the UI.

Generally, code that calls async callbacks should provide an error
handler callback. For example in async requests:

makeRequest(url, {success: callback, error: errback});

In runtime script errors:
//-----------------------------------
// Deferred Callback Error Handling
//-----------------------------------
function deferCallback(f, errback) {
    var wrapped = asyncCallbackWrapper(f, errback);
    setTimeout(wrapped, 100);
}

function asyncCallbackWrapper(f, errback) {
  return _safeWrap;
  function _safeWrap() {
    try {
      f();
    } catch(ex) {
      errback(ex);
    }
  }
}

deferCallback(doSomethingBad, function errback(ex) {
  alert("doSomethingBad threw: " + ex.name +", " + ex.message);
});
-- 
Garrett
@xkit
ChordCycles.com
garretts.github.io


More information about the Noisebridge-discuss mailing list