Working with Promises in Windows Store Apps

Introduction

To deal with the complexity involved in asynchronous programming, Windows Store apps make use of what is known as a Promise. The implementation of Promises in Windows Store apps is based on Common JS Promises proposal. At code level a promise is an object that represents the result of an asynchronous operation and returns a value at some later time in the future. Promises make it easy to work with asynchronous operations in Windows Store apps. This article discusses what promises are and also shows how to use them in a Windows Store app.

Overview of Promise Object

As mentioned earlier at the code level a Promise is an object that represents the result of an asynchronous operation and returns a value at some later point in the future. You can wire functions on a Promise object for the three phases of execution - an asynchronous operation is completed, an asynchronous operation generated an error, and an asynchronous operation is in progress. One of the common situations where you will need to deal with Promises is while calling the xhr() function. The xhr() function is used to make cross-domain HTTP calls to remote resources (say a Web API) and returns a Promise. In the later sections you will see how this Promise object can be dealt with.

Although Promise object has many methods the most commonly used methods are:

  • then()
  • done()

The then() as well as done() method accept three parameters as explained below:

  1. A function that gets executed upon the successful completion of the asynchronous operation (success function or completion function)
  2. A function that gets executed whenever there is some error while executing the asynchronous operation (error function)
  3. A function that can track progress of the asynchronous operation (progress function)

The following piece of code shows the general syntax of then() method along with the three functions mentioned above.

promiseObj.then(successHandler,errorHandler,progressHandler);
function successHandler(req){
   document.getElementById("lblMsg").innerHTML = "Operation was successful!";
}

function errorHandler(err){
   document.getElementById("lblMsg").innerHTML = "There was some error!";
}

function progressHandler(req){
   document.getElementById("lblMsg").innerHTML = "Wait...";
}

The then() and done() are quite similar in terms of the parameters they take. However, an important difference is that the then() method returns a WinJS.Promise object whereas the done() method doesn't return anything. Since then() method returns a Promise object you can chain multiple then() calls whereas you can't chain done() method calls. The done() method must be called as the last method in the call chain. 

Now that you know the basic information about Promises in Windows Store apps, let's see how to use them with an example.

Using Promises with xhr() Calls

As an example you will use the Promise object returned by the xhr() function call. You will use the same example app found in this article - Making HTTP Requests in Windows Store Apps. So make sure to download the source code of the aforesaid article. The code contains a Web API project that contains an ApiController to deal with customer data. The customers Web API  returns a list of Customer objects in its get() method as shown below:

public IEnumerable<Customer> Get()
{
    NorthwindEntities db=new NorthwindEntities();
    var data = from item in db.Customers
	       orderby item.CustomerID
	       select item;
    return data.ToList();
}

If you see the Windows Store app from the solution you will find code that makes use of the xhr() function to call this Web API. The xhr() function returns a Promise object. For the sake of simplicity modify the existing code as shown below:

var options = {
    url: "http://localhost:49177/api/customers",
    type: "GET",
}
var promise = WinJS.xhr(options);
promise.then(successHandler,errorHandler);
function successHandler(req){
   document.getElementById("lblMsg").innerHTML = "Operation was successful!";
}

function errorHandler(err){
   document.getElementById("lblMsg").innerHTML = "There was some error!";
}

In this case you store the Promise object returned by the xhr() function in a local variable. Next, the then() method is called on the Promise object and two functions are passed as the parameters. If you run the Windows Store app and if everything is ok then you should see the message as specified in the successHandler function. To test the errorHandler just change the url option to some invalid url (say change the end point to customers1) and run the app again. This time the control will go to the errorHandler function and an error message is displayed.

Handling Errors in Promises

In the previous section you wired success and error handler functions using the then() method. However, you didn't perform any check in the error handler to figure out what went wrong. In this section you will add that logic so that the end user gets an elaborate and precise error message. Modify the errorHandler function as shown below:

function errorHandler(err) {
  var msg= "";
  if (e.message != undefined) { 
    msg = e.message;
  }
  else if (e.statusText != undefined) {
    msg = e.statusText;
  }
  else {    
    msg = "Unexpected Error !!!";
  }
  document.getElementById("lblMsg").innerHTML = "<strong>" + msg + "</strong>";
}

You can use the parameter passed to the errorHandler function (err) to find out more information about the error. If the URL is malformed the control will go to the first if block and you use the message property of the err object to get the error description. If the URL was correct but there was some error while executing the operation the second if block is called, where you use the statusText property of the err object. For any other cause the else block will be executed and you display a generic error message.

Chaining Promises

You can also chain calls to then() method. This way you can process the result of the asynchronous operation in multiple steps. The following code fragment shows how:

var promise = WinJS.xhr(options);
promise.then(successHandler1)
       .then(successHandler2,errorHandler);

In this case first successHandler1 is executed and then successHandler2 gets executed. If you want to use done() in the chain it must be at the end of the chain.

Handling Timeouts

If you expect any problem while executing the asynchronous operation or if the asynchronous operation is long running, you may want to set a timeout value so that the request is cancelled after a specified time. You can accomplish this task by using the timeout() method of the Promise object. The following code shows how:

WinJS.Promise.timeout(2000,
  WinJS.xhr(options)
      .then(
        function (req) {
                ...
  },
  function error(err) {
                ...
  })
)

It's basically the same xhr() call but with a couple of changes. Firstly, the xhr() call is now wrapped inside Promise.timeout(). The first parameter is the timeout value in milliseconds (2000 in this case) and the second parameter is a Promise object returned by calling then() method.

Note that while using timeout() you must use then() method of the Promise object because then() returns a Promise whereas done() doesn't return any value.

Summary

While dealing with asynchronous operations Windows Store apps use Promise object. The two methods of Promise object, viz. then() and done(), are used to specify success, error and progress handler functions. The then() method returns a Promise and hence calls to then() method can be chained whereas done() doesn't return anything. You can also use Promise object to handle timeouts.



Related Articles

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • IBM Worklight is a mobile application development platform that lets you extend your business to mobile devices. It is designed to provide an open, comprehensive platform to build, run and manage HTML5, hybrid and native mobile apps.

  • On-demand Event Event Date: October 29, 2014 It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this webcast, Gene Kim discusses these survey findings and shares woeful tales of artifact management gone wrong! Gene also shares examples of how high-performing DevOps …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds