How to polyfill JavaScript fetch function for Internet Explorer

Subscribe to my newsletter and never miss my upcoming articles

I love using fetch API for my personal projects. When using Babel and working on the React project, ES6 syntax gets transpiled and polyfilled automatically on build time. But what we need to do when we want to use fetch API on a simple project that doesn't use Babel or Webpack? We need to manually polyfill it, and make sure the additional polyfills do not affect website performance.

A polyfill is a piece of code (usually JavaScript on the Web) used to provide modern functionality on older browsers that do not natively support it.

Why use "fetch"?

Before fetch API was introduced, creating HTTP requests using XMLHttpRequest was complicated and the syntax was not clean and straightforward.

var xhr = new XMLHttpRequest();

xhr.open("GET", "https://path/to/api.endpoint");

xhr.send();

xhr.onload = function() {
  // Handle response
};

xhr.onprogress = function(event) {
  // Handle progress
};

xhr.onerror = function() {
  // Handle error
};

Yeah, that is a lot of boilerplate code separated into multiple class methods and event handlers.

There were also some JavaScript plugins and jQuery (ajax) functions that act as a wrapper around XMLHttpRequest to simplify it and improve the syntax, but there were no official API improvements until ES6 fetch API.

Fetch API

Fetch API allows us to make HTTP requests using much simpler and straightforward JavaScript syntax to send and receive data, and handle any event using JavaScript promises.

fetch("https://path/to/api.endpoint")
  .then(handleResponse)
  .catch(handleFallback);

Looks simple enough, right?

This improved syntax made the whole functionality more accessible and developer-friendly. Although fetch browser support sits at a comfortable 95%, we can easily polyfill it so even more browsers support it.

Polyfilling fetch for Internet Explorer

We don't want to just add the polyfill to the project so it loads for all browsers (including those that support fetch natively). Let's load the polyfill dynamically so extra JavaScript is loaded only if it's required.

For fetch to work on Internet Explorer, we need to add two polyfills:

  • Promise polyfill - remember, fetch uses promises
  • Fetch polyfill
// Detect if user is on IE browser
 var isIE = !!window.MSInputMethodContext && !!document.documentMode;

    if (isIE) {
       // Create Promise polyfill script tag
        var promiseScript = document.createElement("script");
        promiseScript.type = "text/javascript";
        promiseScript.src =
            "https://cdn.jsdelivr.net/npm/promise-polyfill@8.1.3/dist/polyfill.min.js";

      // Create Fetch polyfill script tag
        var fetchScript = document.createElement("script");
        fetchScript.type = "text/javascript";
        fetchScript.src =
            "https://cdn.jsdelivr.net/npm/whatwg-fetch@3.4.0/dist/fetch.umd.min.js";

      // Add polyfills to head element
        document.head.appendChild(promiseScript);
        document.head.appendChild(fetchScript);

      // Wait for the polyfills to load and run the function. 
      // We could have done this differently, 
      // but I've found it to work well for my use-cases
        setTimeout(function () {
            window
                .fetch("https://path/to/api.endpoint")
                .then(handleResponse)
                .catch(handleErrors);
        }, 1000);
    } else {
      // If fetch is supported, just run the fetch function
        fetch("https://path/to/api.endpoint")
                .then(handleResponse)
                .catch(handleErrors);
    }

And that is it. If the user is using Internet Explorer, fetch function will be added to global window object and be used as window.fetch().

Conclusion

I've used this method to load articles from DEV on my personal website using fetch and it works as expected. This was really simple to implement and I was happy with the final results. I was also happy that I'm not loading the polyfills if they're not needed.

Note: Also feel free to leave a comment on how I can improve my code to replace setTimeout function and make sure that this part of the code waits until polyfill becomes available.


These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.

Buy Me A Coffee

Thank you for taking the time to read this post. If you've found this useful, please give it some likes, share and comment.

Comments (2)

V Thulisile Sibanda's photo

Great article and informative 👌🏿

Adrian Bece's photo

Thank you very much!