Concatenating multiple strings from a JSON response

Posted on

Problem

I would like to concatenate a series of strings populated from an XHR response. So, I’ve chosen to do it like this:

$.post('/API',null,'json')
    .done(function(response){
        if (response.status === 'success') {
            location = response.data.city + ', ' + response.data.state;
        }
    })
    .fail(function(){
        location = previousLocation;
    })
    .always(function(){
        $("#location").text(location);
    });

This feels clunky. Should I be more defensive in assuming a response from the API? Would this be more elegantly handled by some kind of templating function?

Solution

I would suggest using then whenever possible. done and fail are specific to jQuery while then is a “standard” pseudo-interface for promises.

And if my jQuery isn’t mistaken, the success handler will fire for 2xx and 3xx responses, while the fail handler will fire on 4xx and 5xx responses. You should take advantage of those instead of returning and checking statuses manually. The only time I remember APIs require using 2xx for errors is for Flash, for some reason.

Assuming response always has a data field and you want everything in the data field to be concatenated, you can use Object.keys, array.map and array.join.

Your code should end up looking like this. Two-space indent is a personal preference, but I go with it because it looks more compact.

$.post('/API',null,'json').then(function(response){
  location = Object.keys(response.data).map(function(key){
    return response.data[key];
  }).join(', ');
}, function(){
  location = previousLocation;
}).always(function(){
  $("#location").text(location);
});

This at least checks for whether there was a response on the needed properties.

$.post('/API',null,'json')
    .done(function(response){
        if (response.status === 'success') {
            var city = response.data.city,
                state = response.data.state;

            location = city ? city : '' + city && state ? ', ' : ''  + state ? state : '';
        }
    })
    .fail(function(){
        location = previousLocation;
    })
    .always(function(){
        $("#location").text(location);
    });

Leave a Reply

Your email address will not be published. Required fields are marked *