1

I am a bit confused as to why my ajax call doesnt return a result. I thought a method defined as async automatically returns a promise. What am I doing wrong?

async AjaxCall(filePath) {
      let xhttp = new XMLHttpRequest();

      xhttp.open('POST', filePath, true);
      xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
      xhttp.send();

     xhttp.onreadystatechange = function() {
          if (xhttp.readyState === 4 && xhttp.status === 200) {
            return xhttp.responseText;
          }
      }
  }


async function Test() {
  var result = await AjaxCall("file.php");
  alert(result);
}

Test();
Asperger
  • 3,064
  • 8
  • 52
  • 100
  • 1
    `AjaxCall` doesn't await anything or return a promise – Liam Jun 20 '18 at 15:33
  • 1
    Possible duplicate of [How do I promisify native XHR?](https://stackoverflow.com/questions/30008114/how-do-i-promisify-native-xhr) – Liam Jun 20 '18 at 15:33
  • Possible duplicate of [AJAX returns null?](https://stackoverflow.com/questions/12662817/ajax-returns-null) – Liora Haydont Jun 20 '18 at 15:34
  • if you're looking for ajax+promises, check out the [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) – Thomas Jun 20 '18 at 15:38

2 Answers2

4

async/await is (really useful) syntactic sugar for creating and consuming promises. Your AjaxCall function implicitly creates a promise, but then also implicitly resolves it immediately with the value undefined because you never await anything, and the only return isn't directly in AjaxCall but is instead in the onreadystatechange callback.

You can wrap a promise around XHR, but you don't have to: fetch already does:

async function Test() {
  var result = await fetch("file.php");
  if (result.ok) {
      alert(await result.text());
   }
}

But if you want to do it yourself, you'll need to explicitly create and consume a promise rather than using async on AjaxCall:

function AjaxCall(filePath) {
    return new Promise((resolve, reject) => {
        let xhttp = new XMLHttpRequest();

        xhttp.open('POST', filePath, true);
        xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        xhttp.send();

        xhttp.onreadystatechange = function() {
            if (xhttp.readyState === 4) {
                if (xhttp.status === 200) {
                    resolve(xhttp.responseText);
                } else {
                    reject(); // Probably including some rejection reason
                }
            }
        };
    });
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

The problem is that you aren't actually returning any data from your function. You are returning data inside the onreadystatechange function but that is just lost and never used. Take a look here specifically this piece of code:

function makeRequest(method, url) {
    return new Promise(function (resolve, reject) {
        let xhr = new XMLHttpRequest();
        xhr.open(method, url);
        xhr.onload = function () {
            if (this.status >= 200 && this.status < 300) {
                resolve(xhr.response);
            } else {
                reject({
                    status: this.status,
                    statusText: xhr.statusText
                });
            }
        };
        xhr.onerror = function () {
            reject({
                status: this.status,
                statusText: xhr.statusText
            });
        };
        xhr.send();
    });
}

You will notice that it has wrapped the entire function in a promise and then you can use the standard async/await functionality when calling it. Async/Await is really just a wrapper around the existing promise functionality.

Adam H
  • 1,750
  • 1
  • 9
  • 24