Tag Archives: promise

Force failure of JavaScript promise in Dojo

For development and unit testing you may need to force a promise chain to fail in various ways.

In listing 1 below is shown a simple XHR request. Now to make sure our promise chain error handling is working correctly we want the Ajax call to fail.

One way of achieving this to just change the url of the XHR destination. This is fine here, but is not a generic approach since not every async function or service is based on a URL or even single value.

Another approach is shown in listing 2. Here we cancel the promise. In Dojo’s promise implementation we can cancel(reason,flag) a promise giving a reason and a flag, and even invoke a cancel handler if the promise was created with one. If this flag is true, a successful async call will result in a failure. Unfortunately, unless you type at superhuman speeds, this can’t be added at a debugger breakpoint and must be coded in temporarily.

Listing 1

/**
 * XHR call.
 * @returns promise
 */
function _loadData(requestParams) {
    var promise;
    require([ "dojo/request"], function(request) {
        promise = request.post("someurl", {
            data : requestParams,
            handleAs : "json",
            preventCache : true
        })
    });
    
    return promise;
}

Listing 2

function _loadData(requestParams) {
    var promise;
    require([ "dojo/request"], function(request) {
        promise = request.post("someurl", {
            data : requestParams,
            handleAs : "json",
            preventCache : true
        })
    });
    
    promise.cancel("force error",true);
    return promise;
}    

There are XUnit type testing frameworks for JavaScript that may be able to do this failure testing better. I have not looked into this yet.

Further reading

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

JavaScript Promise example, reverse geocode location

In prior post we wrapped the Google Map API in a Promise. Now we wrap navigator.geolocation.getCurrentPosition in a similar promise. This allows us to to neatly chain these two to get the browser’s current address.

The example is using Dojo’s Promise implementation, but the approach is applicable to other Javascript Promise libraries or native support.

In listing 1 below I reproduce the former getGeocode function.

Listing 1, Get geocode using Google service

function geoCode(request) {
    var deferred;
    require([ 'dojo/Deferred' ], function(Deferred) {
        deferred = new Deferred();        
        new google.maps.Geocoder().geocode(request, 
          function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                deferred.resolve(results);
            } else {
                deferred.reject(status);
            }
        });
        
    });
    
    return deferred.promise;
    
}

In listing 2 below we have a similar function

Listing 2, get browser location.

function getLocation(){
    var deferred;
    require([ 'dojo/Deferred' ], function(Deferred) {
        deferred = new Deferred();
        navigator.geolocation.getCurrentPosition(
            function navSuccess(position){
                deferred.resolve(position);
            },function navFail(){
                deferred.reject(posError);
            }
        );
    });

    return deferred.promise;
}

Hmmm. The code is very similar. It seems that these two functions could be done using a Promise wrapper function, like toPromise(doFunction, onSuccess, onFailure). Is there such a beast?

Now we can use them together, as shown in listing 3. Here instead of a simple promise chaining we use the technique presented in “Break promise chain and call a function based on the step in the chain where it is broken (rejected)” to “catch” the correct error and not have it bubble up the ‘then’ chain.

Listing 3, get browser location, then reverse geocode

function findCurrentLocation(){
    var request;

    if (navigator.geolocation) {
        getNavLocation().then(
            function navSuccess(position){
                request = {
                    'location' : 
                      new google.maps.LatLng(
                        position.coords.latitude, 
                        position.coords.longitude)
                };

                return getGeoCode(request).
                   otherwise(function geoCodeError(status){
                     throw new Error(status);
                   }
                );
            }, function navFailed(err){
                console.log('navLocation() failed: " + err); 
                throw new Error(err);       
            })
            .then(function geoCodeSuccess(results){
                    console.log('navLocation() success: " + results);
                } 
            );
    }
}

Above, .otherwise(onFailure) is just a shortcut for .then(null, onFailure)

Of course, the code doesn’t have enough error handling and actual use of the data obtained.

Further reading

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Wrap Google map geocoder.geocode in a Promise

Futures and promises are a programming construct to make asynchronous programming easier to apply. They are provided in many JavaScript libraries and frameworks. Below we use Dojo’s implementation to wrap a non-promised based async operation, getting a Geocode from the Google Map API.

The Google geocode service takes a request object (which contains address information) and a callback function that takes a results object and a status string. If status is ok, the results object contains the geocode information (and a lot of other useful information).

In listing one the geoCode function wraps this in a Promise. Inside the function we create a deferred object, then invoke the above async geocode service, then we return the Promise interface of the Deferred object. Note, this is taken from a working application code, and that code works, this below, not tested.

Listing 1.

var geocoder = new google.maps.Geocoder();
 
function geoCode(request) {
    var deferred;
    require([ 'dojo/Deferred' ], function(Deferred) {
        deferred = new Deferred();        
        geocoder.geocode(request, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                deferred.resolve(results);
            } else {
                deferred.reject(status);
            }
        });
        
    });
    
    return deferred.promise;
    
}

You can use this as follows:

var promise = getGeocode(request);

Note that we don’t wait for the async operation to complete, or more correctly, invoke our callback function. The invoker of our geoCode function just gets a Promise object. So?

The Promise object is something that may get a value when it is fulfilled or it may get rejected. You find this out by reacting to those states. How? By using callbacks. So we are right back to where we started, after all the original geocode function also used callbacks. Ah, but here is the difference. With Promises, you are using something with more features and power. The Promise framework allows you to work with async code in a more frameworky way.

One of the nice features of Promises is that they can be “then’able”. “then” functions return a Promise, so they can be chained together: p.then(….).then(….).then(…..); Within each ‘then’, you supply a left and a right callback function, the left is for the resolved, the right is for the rejected state. Example:

var p = getGeocode(request)
p.then(successFunction,failureFunction);

You could also inline everything:

getGeocode(request).then(
    function(results){
       var x = do_something_with_result(results);
       return x;
    },
    function(status){
       do_something_with_status(results);
       throw "failed"
    }
});

These left and right are not chains themselves, there is one chain, but the left or right could be invoked depending on whether the preceding “then” resolved or rejected the promise. Of course, there are more details and each Promise implementation adds their own terminology and features. For example, Dojo has an always function that accepts a callback to invoke no matter what the previous ‘then’ did with the promise.

Apparently moves are afoot to make ‘futures’ part of the core JavaScript standard. These may be following the Promises/A+ specification.

A future blog post will provide a very easy to understand intro to Promises. There doesn’t seem to be a Promise for dummies on the web.

Further reading

YouTube

JavaScript Promises: Thinking Sync in an Async World

Redemption from Callback Hell

Times Developer Network – Promises, Promises

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.