Trevin Avery
Trevin Avery

Reputation: 2919

Load JavaScript file via AJAX without jQuery

I am dynamically loading a widget from another webservice that requires a script to be run immediately after it. The example uses document.write() to do this, but this does not work because it doesn't run until after the document has been closed, which means it overwrites the entire document. I am trying to load it via AJAX using pure JavaScript:

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
  if (this.readyState == 4 && this.status == 200) { // success
    eval(this.responseText);
  }
};
xhttp.open("GET", "https://d3gxy7nm8y4yjr.cloudfront.net/js/embed.js", true);
xhttp.setRequestHeader('Content-type', 'application/javascript');
xhttp.send();

but I get the following error:

XMLHttpRequest cannot load https://d3gxy7nm8y4yjr.cloudfront.net/js/embed.js. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://example.com' is therefore not allowed access.

I was able to make it work using jQuery on my test server with this code:

$.ajax({
    dataType: "script",
    cache: true,
    url: "https://d3gxy7nm8y4yjr.cloudfront.net/js/embed.js"
});

However, I cannot use jQuery on my production server because... well... work politics.

How is jQuery accomplishing this without an error, and how can I do it in pure JavaScript?

Solution

As stated by @shabs, $.ajax adds a script tag to the document.head and then immediately removes it. I checked this by adding a breakpoint and saw it added and removed in Chrome's inspector. It appears to remove the file as soon as the current script completes regardless of what the file is. This works well for immediately invoked scripts, but I don't know how this would work with something like a library.

For a pure JavaScript implementation I used the following code:

var widgetScript = document.createElement("script");
widgetScript.async = true;
widgetScript.src = "https://d3gxy7nm8y4yjr.cloudfront.net/js/embed.js";
document.head.append(widgetScript);
widgetScript.remove();

Upvotes: 2

Views: 2654

Answers (1)

shabs
shabs

Reputation: 718

The resource in question doesn't support CORS.

This works through $.ajax because when you specify dataType: "script", jQuery actually appends a <script> tag to document.head! *

Is there a particular reason you're not just using something like <script type="text/javascript" src="https://d3gxy7nm8y4yjr.cloudfront.net/js/embed.js"></script>?

* (This is news to me! The documentation for $.ajax mentions that "script [...] requests are not subject to the same origin policy restrictions", and the source code confirms this.)

Upvotes: 2

Related Questions