Where'd Promise#done go?

Chad Austin chad at imvu.com
Wed Jun 19 11:56:32 PDT 2013


On Wed, Jun 19, 2013 at 7:01 AM, Mark S. Miller <erights at google.com> wrote:

> On Wed, Jun 19, 2013 at 3:28 AM, Alex Russell <slightlyoff at gmail.com>wrote:
>
>>
>> What was less clear is that there's any real problem with error handling:
>> polyfills can (should?) keep lists of unhandled promises and make them
>> available to tools while we wait for devtools to surface the list. The
>> concerns here with direct logging seem, to me, to be premature.
>>
>
Last night I converted a bunch of our continuation-passing code to use
promises, so now I have both implementation and usage experience with the
current promise proposal.  Inadvertent error swallowing and incomplete
error bubbling were the primary pain points.  I frequently found myself
with typos and mistakes that became opaque TypeErrors by the time they
reached the browser debugger or error log.

A DOM promise polyfill, in current web browsers*, cannot provide the same
level of error handling and reporting as we've come to expect in
traditional onload/onerror asynchronous code.  Consider:

Promise.fulfill({}).then(function(x) {
    //...
    x.oops_not_a_function();
    //...
});


A naive polyfill would swallow ReferenceError or TypeError and hide it
completely.  So let us suppose that the polyfill keeps lists of unhandled
rejections.  How does the promise debugger know whether promises are still
live and simply don't have reject callbacks configured yet?  In addition,
by the time the error in inspected, the stack trace is gone as well as any
activation records, so even though Chrome and Firefox provide Error#stack,
there's no way to inspect into 'x'.  This is reproducible by bubbling the
error with setTimeout:

function bubbleToBrowser(e) {
    setTimeout(function() {
        throw e;
    }, 0);
}

Promise.reject(new Error("will_bubble")).catch(function(e) {
    bubbleToBrowser(e);
});


Or its fundamental equivalent:

try {

    ({}).not_a_function();
}

catch (e) {

    setTimeout(function() {

        throw e;

    }, 0);

}

It's very hard in practice to trace the error back to its original cause.
 There are two issues here:

   1. Something like Promise#done allows idiomatically expressing "No
   really, that's it, don't chain anymore, and bubble errors into the event
   loop"
   2. Bubbling errors to the main loop with useful amounts of information
   is not possible in current browsers and JavaScript.

In the meantime, I will likely add an option to our Promise implementation,
and perhaps default it on, that makes no attempt to catch errors thrown in
Promise callbacks, guaranteeing they reach the event loop at the time
they're thrown.

Thanks,
Chad

* I am happy to live with limitations of current web browsers as long as
there is a clear plan to solve them.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130619/a25c5979/attachment.html>


More information about the es-discuss mailing list