Get #Amazon #Prime for this #holiday #amazonprime #christmas #2019

Turn #XMLHttpRequest into a #Promise #XHR

By Jun - Support me on Amazon Canada

How to turn XMLHttpRequest / XHR into a Promise so that you can chain it with other promises?

First of all, if you don't know what XMLHttpRequest is, you can check out MDN document on XMLHttpRequest. In short, it is an API that can be used by a JavaScript to communicate to servers. It enables asynchronous HTTP requests.

XMLHttpRequest Ready States
XMLHttpRequest Ready States


Situation:

You might wonder why not using Fetch (definition on MDN) which is the new way of fetching data  asynchronously from servers. Well, they work quite similarly but not exactly the same. I am not sure about how many cases there are but there is this case that I have to use XHR instead of Fetch.

Issues that I faced:

Using fetch for a cross origin request(url is set in the permission in manifest) in chrome extension set origin header as null and doesn't sell referer header in the request.
Thus, I cannot use origin and referer header to identify if a request is coming from my chrome extension.
i) Using fetch in chrome extension sends null origin header StackOverflow thread
ii) Using fetch in chrome extension doesn't include referer header in the request StackOverflow thread

As a result, I have to use XHR to do it.

How to turn XMLHttpRequest / XHR into a promise?

This is an example of how you can return a Promise that contains an XMLHttpRequest.


function xhr(params) {
  return new Promise(function(resolve, reject) {
    let xhr = new XMLHttpRequest();
    let url = '';

    xhr.open('POST', url + params);

    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.responseType = 'blob';

    xhr.onreadystatechange = function() {
      if (xhr.readyState == XMLHttpRequest.DONE && xhr.status >= 400) {
        let ress = xhr.response;

        if (typeof res.errorCode !== 'undefined') {
          reject(new Error('Something went wrong...));
        }
      }

      if (xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
        let res = xhr.response;
        resolve(res);
        // do something with response
        // let blobUrl = window.URL.createObjectURL(blob);
        // resolve(blobUrl);
      }

      if (xhr.readyState == 2) {
        // do something at HEADERS_RECEIVED state
        // eg. setting responseType, setting ui etc
        // xhr.responseType = 'json';
      }
    }
    
    // you can also listen for onload and onerror events
    // instead of using onreadystatechange
    xhr.onload = function() {
      // do something with response
      let res = xhr.response;
      resolve(res);
    };

    xhr.onerror = function() {
       reject(new Error('error'));
    };

    // send request
    body = JSON.stringify({ params });
    xhr.send(body);
  })

Note:
I have also created a post in chromium extension discussion group. You can check it out and see if there is any update from chromium.

Thank you for reading!