From: [email protected] [mailto:[email protected]] 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
[email protected]
https://mail.mozilla.org/listinfo/es-discuss