简体   繁体   中英

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, eg 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?

In order for async and await to work you need to return something from your await ed call that the JS runtime can use to know when to continue the function that is await ing 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();
  });
}

You need to return a promise from the ajaxCall(). Code should look something like that:

function ajaxCall() {
  return new Promise((resolve, reject) => {
    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));
          resolve(JSON.parse(xmlhttp.response));
        }
      }
    // handle error: reject(error);
    }
    xmlhttp.open('GET', url, true);
    xmlhttp.send();
  })
}

then:

async function getData() {
    try {
        let data = await ajaxCall();
        console.log(data);
    } catch (e) {
        // do something with error
    }
}

Note that I used es6 arrow functions

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM