Solo Solo - 4 months ago 18
Javascript Question

Babel async await

I've spent last few hours trying to make it work but it just doesn't for no apparent reason. I have all the required packages and settings. I get no errors,

async
and
await
just doesn't wait.

I use Webpack to require the polyfill files that Babel adds, e.g
babel-runtime/regenerator
.

Code:



async function getData() {
let data = await ajaxCall();
console.log(data);
}

function ajaxCall() {
let url = 'https://maps.googleapis.com/maps/api/geocode/json?address=london';

let xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if(xmlhttp.status == 200) {
console.log(JSON.parse(xmlhttp.response));
return JSON.parse(xmlhttp.response);
}
}
}
xmlhttp.open('GET', url, true);
xmlhttp.send();
}

getData();

// It logs "undefined" and then ajax response AFTER





.babelrc:



{
"presets": ["es2015", "stage-0"],
"plugins": ["transform-runtime"]
}


Does anyone have any idea what could be wrong?

Answer

In order for async and await to work you need to return something from your awaited call that the JS runtime can use to know when to continue the function that is awaiting the result. The "type" that is required for async / await interop is called Promise.

Your ajaxCall returns undefined, which doesn't tell the JS runtime anything, so it doesn't await because there is nothing to wait for. If you want to make this work, simply return a Promise from ajaxCall and resolve it when your ajax request is fulfilled.

At the simplest:

function ajaxCall() {
  let url = 'https://maps.googleapis.com/maps/api/geocode/json?address=london';
  // The new `window.fetch` API returns a promise for you
  return fetch(url).then(response => response.json());
}

or using XMLHttpRequest:

function ajaxCall() {
    let url = 'https://maps.googleapis.com/maps/api/geocode/json?address=london';
    return new Promise((resolve, reject) => {
      let xmlhttp = new XMLHttpRequest();
      xmlhttp.onreadystatechange = () => {
        if (xmlhttp.readyState == XMLHttpRequest.DONE) {
          if (xmlhttp.status == 200) {
            // resolve instead of return inside of a Promise closure
            resolve(JSON.parse(xmlhttp.response));
          } else {
            // reject instead of throw
            // (will throw the error at the `await` expression.)
            reject(Error(`Received status code ${xmlhttp.status}`));
          }
        }
    }
    xmlhttp.open('GET', url, true);
    xmlhttp.send();
  });
}
Comments