Vanilla JavaScript, AJAX, and APIs

Vanilla JavaScript, AJAX, and APIs
0.0 0

#1

Hi all,

I’m working on the random quote generator project, and I’m trying to do it with vanilla JavaScript (i.e., no JQuery). Here is what the documentation says for a simple HTTP request:

<button id="ajaxButton" type="button">Make a request</button>

<script>
(function() {
  var httpRequest;
  document.getElementById("ajaxButton").addEventListener('click', makeRequest);

  function makeRequest() {
    httpRequest = new XMLHttpRequest();

    if (!httpRequest) {
      alert('Giving up :( Cannot create an XMLHTTP instance');
      return false;
    }
    httpRequest.onreadystatechange = alertContents;
    httpRequest.open('GET', 'test.html');
    httpRequest.send();
  }

  function alertContents() {
    if (httpRequest.readyState === XMLHttpRequest.DONE) {
      if (httpRequest.status === 200) {
        alert(httpRequest.responseText);
      } else {
        alert('There was a problem with the request.');
      }
    }
  }
})();
</script>

Why does the code include the following:

if (!httpRequest) {
  alert('Giving up :( Cannot create an XMLHTTP instance');
  return false;

More specifically, what role is !httpRequest playing?


#2

I’m going to go out on a limb here and guess that’s because really old browsers (IE specifically) don’t support new XMLHttpRequest().


#3

This is just some feature detection. Some (very old) browsers don’t use the XMLHttpRequest object, and trying to run the rest of the code without it would just produce errors. Best to eject early.

Don’t use XHR, though. It’s an old API that’s on the way out. Almost all browsers use the fetch API now, so throw in a fetch polyfill and learn the new and improved way to make AJAX calls in JavaScript.


#4

Thanks, guys!

Also, super helpful video.


#5

It is interesting you say not to use XHR, because when I look at the fetch.js file, it looks like it uses XHR (unless I am reading it wrong).

  self.fetch = function(input, init) {
    return new Promise(function(resolve, reject) {
      var request = new Request(input, init)
      var xhr = new XMLHttpRequest()

      xhr.onload = function() {
        var options = {
          status: xhr.status,
          statusText: xhr.statusText,
          headers: parseHeaders(xhr.getAllResponseHeaders() || '')
        }
        options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
        var body = 'response' in xhr ? xhr.response : xhr.responseText
        resolve(new Response(body, options))
      }

      xhr.onerror = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.ontimeout = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.open(request.method, request.url, true)

      if (request.credentials === 'include') {
        xhr.withCredentials = true
      }

      if ('responseType' in xhr && support.blob) {
        xhr.responseType = 'blob'
      }

      request.headers.forEach(function(value, name) {
        xhr.setRequestHeader(name, value)
      })

      xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
    })
  }

#6

You’re reading the polyfill, which is only used if the browser doesn’t have a native fetch object.


#7

Doh! That makes sense.