Callbacks & promises in JS for newbies

How to use callbacks or promises with Google Maps Javascript API

Posted on Sun 02 April 2017

You are a newbie in JavaScript? You want to know a little bit more about asynchronous nature of this language? Join me!

Table of Contents:

Problem

I was working on my project that is using Google Maps. I stumbled upon an issue - how I display a map after submitting a form with geocoded address in it?

After some research, I found that I need first geocode and then if it passes to render the map with a custom marker.

I did this and it doesn't work! I try one more time and one more. After one hour I decided to write a question on stackoverflow.

Guys there flagged it as a duplicate and told me you should look into how to handle an asynchronous call. It was confusing - how this is near rendering a map after submitting a form?

I dig more and ask a question on reddit. Then I got my answer - use callback or promise!

Solution

Based on an answer from adavidmiller from reddit I was able to write this code:

function geocodeAddress(address, callback) {
  const geocoder = new google.maps.Geocoder();
  geocoder.geocode({
    address,
  }, function (results, status) {
    if (status === 'OK') {
      callback({
        lat: results[0].geometry.location.lat(),
        lng: results[0].geometry.location.lng(),
      });
    } else {
      alert('Cannot find address');
    }
  });
}

There is a extra argument to this function called callback. It will be executed if everything goes properly. What can be this callback? Look at this:

function onGeocodeComplete() {
  const map = new google.maps.Map(
    mapElem, {
      zoom: 4,
      center: coords
    });
  const marker = new google.maps.Marker({
    position: coords,
    map,
  });
}

In this function, I create a new map that is centered in coords. How will JavaScript know local variable coords? Because it is callback passed to geocodeAddress:

function initMap() {
  searchForm.addEventListener('submit', (event) => {
    event.preventDefault();
    questionForm.classList.add('is-hidden');
    const place = searchForm.querySelector('[name=place]').value;
    geocodeAddress(place, onGeocodeComplete);
  });
}

Look at the last line in this function - this is a place where I pass address which is value from submitted form and I pass callback which is whole onGeocodeComplete function.

You may say 'It looks neat - let's use callbacks! but in many cases this can lead to so called callback hell. To avoid that in ES6 is new way to handle asynchronous JavaScript - Promise.

The same function - geocodeAddress writen using promise:

function geocodeAddressPromise(address) {
  return new Promise((resolve, reject) => {
    const geocoder = new google.maps.Geocoder();
    geocoder.geocode({
      address,
    }, (results, status) => {
      if (status === 'OK') {
        resolve({
          lat: results[0].geometry.location.lat(),
          lng: results[0].geometry.location.lng(),
        });
      } else {
        reject('Cannot find address');
      }
    });
  });
}

The code looks almost the same as in callback but this function returns promise. If the promise was resolved - a.k.a everything goes smoothly it will return lat & lng. In other case information about the error will be returned.

How to handle such promise? You can use that:

function initMap() {
  searchForm.addEventListener('submit', (event) => {
    event.preventDefault();
    questionForm.classList.add('is-hidden');
    const place = searchForm.querySelector('[name=place]').value;
    geocodeAddressPromise(place).then((response) => {
      onGeocodeComplete(response);
    }, (error) => {
      alert(error);
    });
  });
}

I resolve a promise by calling then on it. I pass here arrow function with a response if the promise was resolved. In another case, I just display an error to the user.

What I've learn

I learn quite a lot from having this kind of problem:

  1. what does it mean to write and use asynchronous code in Javascript
  2. what is difference between callback & promise
  3. how to write code using both callback & promise

That's all for today! Feel free to comment - all are realy valuable for me. I just want to thank one more time adavidmiller for taking his time to show me how to write code using callbacks.

Cover image from Unsplash under CC0.

If you find this blog post interesting please share:

Comments !