From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On 
Behalf Of Kevin Smith
Sent: Wednesday, November 7, 2012 09:58

> The only hard part that isn't really addressed by currently library 
> implementations is error handling.  I feel pretty strongly that rejections 
> (and by extension, errors thrown from `then` callbacks), should ALWAYS be 
> observable.  In other words, if a rejection is not observable via error 
> listeners at the time when error listeners should be called, then an 
> unhandled error should be thrown by the runtime.

> In my usage of promises I have never wanted anything other than this behavior.

The problem with this is that it disallows treating promises as first-class 
objects that can be passed around, unobserved, only to be observed at a later 
date. As a trivial example, consider:

```
let promise = Q.reject(); // a rejected promise

setTimeout(=> {
    promise.then(null, (err) => {
        console.err("Got an error!", err);
    });
}, 100);
```

In this example there is nobody observing the promise at the time it is 
rejected, or even a tick after rejection. So should the rejection be thrown by 
the runtime? You would suggest yes. But then the error handling code inside the 
`setTimeout` will never be called.

---

OK, so that's a trivial example. What about a less trivial example? Well, 
consider using promises as remote objects. A rejected promise could be passed 
across the wire in various ways, all of which take much longer than a single 
tick. Or consider just normal control flow that uses promises as first-class 
mechanisms of state. For example the upthread-mentioned promises in place of 
loading events: many libraries will only end up listening to loading events far 
after they are completed, since the loading promise is a first-class observable 
property of the object being loaded (page, image, database, etc.).

In short, it creates a serious refactoring hazard. If you accept a promise, you 
can no longer introduce asynchronicity into your functions that handle it 
(ironic!) due to the risk of its errors escaping you:

```
function processData(promiseForDatabase) {
    // All good:
    return promiseForDatabase.then(=> ..., => ...)
}

function processData(promiseForDatabase) {
    // No good!! You lost the state of `promiseForDatabase`. Its errors have 
escaped,
    // possibly crashing your app if you are e.g. in a Node.js or Windows 8 
Metro environment.
    return getDataForPreprocessing().then(=> {
        return promiseForDatabase.then(=> ..., => ...);
    });
}
```

---

As mentioned upthread, this is solved by task.js, but this is by far the 
thorniest issue faced by promise implementations today. In Q and WinJS, the 
solution is to always "cap" your promise chains with `.done()`. So all promise 
code should either be returning the promise, or capping with `.done()`. Other 
mechanisms we are considering are mostly about enabling greater visibility into 
any currently-unhandled rejections. For example, some type of 
Q.onunhandled/Q.onhandled pair, or integration into some simple browser-console 
extensions that would create a pane where you could view such rejected 
promises, or a mode that sets a maximum timeout before we consider an unhandled 
rejection erroneous and throw it (for development purposes), or somehow showing 
the errors on "exit" (page unload, process exit in Node, ...).
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to