March 12, 2012 telerik win8

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:

  1. 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:

  1. 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:

  1. 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:

  1. 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:

image

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:

  1. 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:

  1. var app = WinJS.Application;
  2. app.onactivated = function (eventObject) {
  3.   // start the download
  4.   downloadStatus.innerText = downloading posts…”;
  5.  
  6.   // process the declarative controls
  7.   WinJS.UI.processAll()
  8.   .then(function () {
  9.     // use the WinRT to download the RSS
  10.     var syn = new Windows.Web.Syndication.SyndicationClient();
  11.     var url = new Windows.Foundation.Uri(http://blogs.msdn.com/b/oldnewthing/rss.aspx”);
  12.     return syn.retrieveFeedAsync(url);
  13.   })
  14.   .done(processPosts, downloadError);
  15. };

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.