WinJS Promises: then and done
As of the Windows Consumer Preview (aka Win8 Beta), the WinJS promises object has a “done” method as well as a “then” method. The “done” method is just like “then” except that it turns unhandled errors into exceptions. If you read no further, know this:
Always call “done” as the last promise method in your promise chain.
Let’s say you have a promise implementation that makes failure a strong possibility:
- var prom = new WinJS.Promise(function (c, e, p) { e(“#fail”); });
A fastidious developer will always pass in an error handler whenever then call the “then” method of a promise:
- prom.then(…, function (m) { content.innerText = “Handled: ” + m; });
However, in the case that the developer doesn’t pass in a error handler function when calling “then”, the error will silently drop on the floor:
- prom.then(); // error? what error?
I realize that the web was built around the idea that page errors should just silently whistle into the wind, but as an app developer:
Errors should be loud.
So, I want my errors to be loud, I should default to using the “done” method on a promise instead:
- prom.done(); // error == BOOM!
When I call the “done” method and an unhandled error is detected, WinJS throws an error that not even a try-catch handler will stop from showing in the developer’s face:
Personally, I’d prefer to be able to catch such errors in try-catch blocks, but this behavior is far preferable to the error being ignored. Of course, if I care that much, I can provide an error handler function when calling done:
- prom.done(…, function (m) { content.innerText = “Handled: ” + m; });
And finally, if I want to chain my promises, I just need to put the “then” methods in between so the errors flow, but the “done” method should always be last:
- var app = WinJS.Application;
- app.onactivated = function (eventObject) {
- // start the download
- downloadStatus.innerText = “downloading posts…”;
- // process the declarative controls
- WinJS.UI.processAll()
- .then(function () {
- // use the WinRT to download the RSS
- var syn = new Windows.Web.Syndication.SyndicationClient();
- var url = new Windows.Foundation.Uri(“http://blogs.msdn.com/b/oldnewthing/rss.aspx”);
- return syn.retrieveFeedAsync(url);
- })
- .done(processPosts, downloadError);
- };
This is actual code from an app that pulls down an RSS feed after the processAll method is completed in the “then” method on line 8, which returns another promise on line 12. That promise is handled by the “done” method on line 14. If there had been an error in the download and as a developer, I’d forgotten to provide the “downloadError” error handler, I’d have gotten a giant exception dialog that would’ve encouraged me down a different path.
Thanks to Josh Williams from the WinJS team for reminding me of the “done” method.