City Photo Finder

Using Foursquare API, Ajax, and Promises

Posted on 2016-02-04 09:02:00 in webdev, javascript, API

Foursquare API

Foursquare's API lets you find venues in any given city. It also lets you find photos of any venue given its unique id. I combined these two endpoints:

api.foursquare.com/v2/venues/search/ api.foursquare.com/v2/venues/{venue_id}/photos

to make a tool that finds pictures from any city.

Promises

I'm still getting my head wrapped around what JS Promises can do. At a basic level, a promise represents a value that will exist in the future. To construct a Promise, you pass it one argument--a callback with two parameters, resolve and reject. Once a promise is defined and returned, you can chain functions to it that run only when the promise has failed or been resolved.

Here's a good example I found showing the basic functionality of a promise:

var promise = new Promise(function(resolve, reject) {
    // do a thing, possibly async, then…
    if (/* everything turned out fine */) {
        resolve("Stuff worked!");  }  
    else {
        reject(Error("It broke"));
    }
});

(Source: html5rocks.com)

Now, with these resolve and reject states, you can do something like this:

promise.then(function(result) {
    console.log(result); // "Stuff worked!"
}, function(err) {
    console.log(err); // Error: "It broke"
});

When the promise is resolved then the function will be called. This is useful for ajax calls. I used the resolve states of promises to chain multiple functions together in this project:

function downloadPhotosByLocation(loc){
    // find venues and get the pictures from each one
    var endpoint = 'venues/search';
    var url = makeUrl(endpoint, ['near', loc]);
    return getJSON(url).then(function(response) {
	  return response.response.venues;
    }).then(function(venues){
        return venues;
    }).catch(function(err){
        console.log('Error!', err);
    }).then(function(venues){
        storeVenues(venues);
	for(var i = 0; i < venues.length; i++){
	    getPictures(venues[i]);
	};
    });

getJSON() is just a helper function that calls get(), which returns a promise. That's why I could attach .then(function()... to getJSON().

Here is my get() function which I use to make all my GET requests:

function get(url) {
    return new Promise(function(resolve, reject) {
        var req = new XMLHttpRequest();    
        req.open('GET', url);    
        req.onload = function() {      
            if (req.status == 200) {
                resolve(req.response);
            }
            else {
                reject(Error(req.statusText));
            }
        };
        req.onerror = function() {
            reject(Error("Network Error"));
        };
        req.send();
});



See it on Github