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