DEV Community

loading...
Cover image for How to polyfill JavaScript fetch function for Internet Explorer

How to polyfill JavaScript fetch function for Internet Explorer

Adrian Bece
React, Frontend, Magento 2 certified developer. Magento PWA Studio contributor. Rock and metal music fan. Reads Dune, sci-fi novels and Calvin & Hobbes. Creates amazing interfaces @ prototyp.digital
・3 min read

I love using fetch API for my personal projects. When using Babel and working on 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
};
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

Looks simple enough, right?

This improved syntax made the whole functionality more accessible and developer-friendly. Although fetch browser support sits at 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 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);
    }
Enter fullscreen mode Exit fullscreen mode

And that is it. If 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 a ❤️ or 🦄, share and comment.

Discussion (5)

Collapse
hispanic profile image
Michael Harry Scepaniak

Thanks for posting. I found this helpful. However, instead of testing for IE, it seems more robust to mimic/duplicate the test that the fetch polyfill, itself, performs, like so:

var testGlobal =
    (typeof globalThis !== 'undefined' && globalThis) ||
    (typeof self !== 'undefined' && self) ||
    (typeof global !== 'undefined' && global)

if (!testGlobal.fetch) {
    ...
}
Enter fullscreen mode Exit fullscreen mode

github.com/github/fetch/blob/maste...

Mike....

Collapse
dlnr profile image
Niels Roozemond

What about not using a polyfill? It's 2020. How many visitors would really be bothered? People using ie9 should be used to getting errors and exploded layouts anyway.

Collapse
adrianbdesigns profile image
Adrian Bece Author • Edited

I still want to support IE11 as it comes pre-installed on Windows machines alongside Edge by default. It's okay to support it in this way since the polyfills don't affect performance on supported browsers.

I don't see any issue here. It's always okay to support older browsers and ensure good UX for them if it's viable and if it's not at performance cost, no matter which year it is.

Collapse
dlnr profile image
Niels Roozemond

Sure it's a hard sell but my point is that all that backward compatibility is holding back the platform as a whole. And Edge should have replaced IE.

Collapse
tc79 profile image
tc79

That's easy to say, but a lot of enterprise environments still use IE on their workstations. They will expect their site to perform as normal.