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.

Comments !