Using JavaScript to perform a GET request without AJAX - javascript

Out of curiosity, I'm wondering about the best (easiest, fastest, shortest, etc; make your pick) way to perform a GET request in JavaScript without using AJAX or any external libraries.
It must work cross-browser and it's not allowed to distort the hosting web page visually or affect it's functionality in any way.
I don't care about headers in the request, just the url-part. I also don't care about the result of the request. I just want the server to do something as a side effect when it receives this request, so firing it is all that matters. If your solution requires the servers to return something in particular, that's ok as well.
I'll post my own suggestion as a possible answer, but I would love it if someone could find a better way!

Have you tried using an Image object? Something like:
var req = new Image();
req.onload = function() {
// Probably not required if you're only interested in
// making the request and don't need a callback function
}
req.src = 'http://example.com/foo/bar';

function GET(url) {
var head = document.getElementsByTagName('head')[0];
var n = document.createElement('script');
n.src = url;
n.type = 'text/javascript';
n.onload = function() { // this is not really mandatory, but removes the tag when finished.
head.removeChild(n);
};
head.appendChild(n);
}

I would go with Pekka idea and use hidden iframe, the advantage is that no further parsing will be done: for image, the browser will try to parse the result as image, for dynamically creating script tag the browser will try to parse the results as JavaScript code.. iframe is "hit and run", the browser doesn't care what's in there.
Changing your own solution a bit:
function GET(url) {
var oFrame = document.getElementById("MyAjaxFrame");
if (!oFrame) {
oFrame = document.createElement("iframe");
oFrame.style.display = "none";
oFrame.id = "MyAjaxFrame";
document.body.appendChild(oFrame);
}
oFrame.src = url;
}

Related

Is using XMLHttpRequest() an outdated way to make an Ajax call?

I'm simply using an example from a book I'm reading. The example is labeled, "Loading HTML with Ajax." This is the JS portion of the code:
var xhr = new XMLHttpRequest();
xhr.onload = function() {
if(xhr.status === 200) {
document.getElementById('content').innerHTML = xhr.responseText;
}
};
xhr.open('GET', 'data/data.html', true);
xhr.send(null);
I'm getting the CSS portion of the code (headers, etc.) when I load the page onto the browser but none of the JS (there should be maps which would load onto the page). The example says I should comment out this portion of the code above:
xhr.onload = function() {
if(xhr.status === 200) {
document.getElementById('content').innerHTML = xhr.responseText;
...if I'm running the code locally without a server but that's not working, either.
Is using XMLHttpRequest() an outdated way to make an Ajax call?
Yes, but it still works and that's not the problem. The more modern way is fetch.
I'm getting the CSS portion of the code (headers, etc.) when I load the page onto the browser but none of the JS (there should be maps which would load onto the page).
That's because assigning HTML that contains script tags to innerHTML doesn't run the script defined by those tags. The script tags are effectively ignored.
To run those scripts, you'll need to find them in the result and then recreate them, something along these lines:
var content = document.getElementById('content');
content.innerHTML = xhr.responseText;
content.querySelectorAll("script").forEach(function(script) {
var newScript = document.createElement("script");
newScript.type = script.type;
if (script.src) {
newScript.src = script.src;
} else {
newScript.textContent = script.textContent;
}
document.body.appendChild(newScript);
});
Note that this is not the same as loading the page with script elements in it directly. The code within script tags without async or defer or type="module" is executed immediately when the closing script tag is encountered when loading a page directly (so that the loaded script can use document.write to output to the HTML stream; this is very mid 1990s). Whereas in the above, they're run afterward.
Note that on older browsers, querySelectorAll's NodeList may not have forEach, that was added just a few years ago. See my answer here if you need to polyfill it.
Because I didn't completely understand T.J.'s answer (no offense, T.J.), I wanted to provide a simple answer for anyone who might be reading this. I only recently found this answer on Mozilla.org: How do you set up a local testing server? (https://developer.mozilla.org/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server). I won't go into details, I'll just leave the answer up to Mozilla. (Scroll down the page to the section titled, "Running a simple local HTTP server.")

Break connection to site from the JS console

In Chrome I have populate an on line mapping tool (Kumu) with a JSON file from the JS Console with:
Workflows.setCurrentMapSource("MY_JSON_LINK");
where MY_JSON_LINK was:
https://XXXXXX/json?key=MTE3.DI4LYA.ZrzRFJ5o7Q5m3nLe6d6JGFISdKI
But the Link is no longer active so when I go to the Kumu page I get the error:
Unable to open map
Is there a way to break the connection from the JS Console? I have searched but have not found anything that works
Thanks
I'm on phone so I can't give you the code, but what you can do is override the XMLHttpRequest methods and then you can manipulate any requests done on the page.
But this must of course be done BEFORE the requests are done so you'll probably need Tampermonkey userscript. Example:
const originalOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function (){
//do what you need
originalOpen. apply(this, arguments);
}
So for example if you want to protect some link from being accessed, you can do this:
const originalOpen = XMLHttpRequest.prototype.open;
const REGEX_TEST_URL = /https?:\/\/XXXXXX\/json?key=(.*?)/
XMLHttpRequest.prototype.open = function (method, url){
console.log("Open: ", url);
/// if you want to kill access to that URL
if(REGEX_TEST_URL.test(url))
throw new Error("Blocked loading of URL "+url)
//Otherwise allow normal operatio to proceed
originalOpen.apply(this, arguments);
}
You can test this even here on stackoverflow.

How to make browser save a remote file and get informed by a callback with Javascript/jQuery

I have encountered a problem with my Java script/jQuery code.
I want to make a piece of code which could fulfill the following requirement:
1.Make the browser save my remote binary file, let's say http://192.168.0.100/system/diagdata
2.Since the preparing the file in the server side with cost some time(usually around 40s), so I need a callback to let me know when the data will be ready to download(the file itself is very small, so let's ignore the actually data transmit duration) so that I could display some kind of loading page to tell the user the downloading procedure is on the way.
At first, I make a piece of code like this without callback:
var elemIF = document.createElement("iframe");
elemIF.src = 'http://192.168.0.100/system/diagdata';
elemIF.style.display = "none";
document.body.appendChild(elemIF);
It works well(but without callback)
Then in order to make callback possible, then I added some code like this:
var deferred = jQuery.Deferred();
var elemIF = document.createElement("iframe");
elemIF.src = 'http://192.168.0.100/system/diagdata';
elemIF.style.display = "none";
document.body.appendChild(elemIF);
elemIF.defer = 'defer';
if (window.ActiveXObject) { // IE
sc.onreadystatechange = function() {
if ((that.readyState == 'loaded'
||that.readyState == 'complete') ) {
}
}
}
else { // Chrome, Safari, Firefox
elemIF.onload = function() {
alert("onload");
};
elemIF.onerror = function(e) {
alert("onerror");
};
}
deferred.promise();
After I run this piece of code, the "onload" has been called, but the browser did not tend to save the file "diagdata" but try to load it and report a parsing error exception.
Did anyone have a substitute solution which could not only make browser save the binary file but also will callback to inform the data ready status?

AJAX for loading code

Some days ago I came across with Polymer project and web components. It is said to be the future of the web. I do not know much about this. But if I understood well, the idea is to enhance the web code modularity. I would like to ask a simple question, at this respect.
Is there any disadvantage or objection to use AJAX in order to read a presuntly "plain text" file (but with HTML, CSS and JS) and use the "document.write" JavaScript function for inserting that code into a different file? I wondered this, because this seems to solve web code modularity in a very easy and fast way. Is there any problem in doing that?
Thank you!
The general principle is fine, but certainly using document.write is terrible. document.write cannot be safely used after the document is fully parsed. Therefore, it will be unsafe to use after an asynchronous load of a resource.
A much better approach is to create a DOM node, load the fetched resource into the node, and then load the node into DOM. For example, asynchronously loading a script (but the general principle is generalizable to other resources as well):
var xhr = new XMLHttpRequest();
xhr.open("GET", "somescript.js");
xhr.send();
xhr.addEventListener("load", function(e) {
var fetchedScriptContent = e.target.responseText
var s = document.createElement("script");
s.textContent = fetchedScriptContent;
// s.innerText = fetchedScriptContent; // for older browsers
document.body.appendChild(s);
});
There is no problem doing that, except document.write won't work after the page has loaded but it is common usage to do something like this to load scripts at runtime:
function addScript(anUrl) {
var aScript = document.createElement( 'script' );
aScript.type = 'text/javascript';
aScript.src = anUrl;
$("head").append( aScript );
}
The browser will take care of loading and running the script from the url, so you do not need to insert the source manually, but if you need, you can do this way:
function addScriptSource(sourceText) {
var aScript = document.createElement( 'script' );
aScript.type = 'text/javascript';
aScript.textContent = sourceText;
$("head").append( aScript );
}

Using Blob WebWorker to send Synchronous XMLHttpRequest

First off, I am very new to web services, web workers, and XMLHttpRequests, so please bear with me. Also, there are a lot of stipulations in my project, so solutions to "just do it this way" may not be viable.
So I have a web service set up to receive calls from an XMLHttpRequest in javascript, and it does this synchronously. This works fine, but it ties up the UI thread, and I would like to have a loading spinner run while making the requests to the server. Due to one issue, I can't have the program access external scripts on the web, so I am using a Blob to mask the "file://" preface.
I am also using an inline webworker to accomplish this. Now I'm getting to my actual issue. Spawning the webworker is fine, and I can create and send the XMLHttpRequest, but as soon as I call "send" everything exits. It will run no lines of code after this.
Here's some code:
Called from JS:
var blob = new Blob([document.querySelector('#getWorker').textContent]);
var blobUrl = window.URL.createObjectURL(blob);
var worker = new Worker(window.URL.createObjectURL(blob));
worker.onmessage = function (e) {
alert(e.data);
}
worker.postMessage();
The worker:
var bigString = "";
var invocation = new XMLHttpRequest();
var url = 'http://<ipAddress>/<serviceName>/Service.asmx/<method>';
if (invocation) {
invocation.open('GET', url, false);
invocation.send(); //*****EXITS AFTER THIS LINE*****//
if (invocation.status == 200) {
var responseText = invocation.responseText.replace(/(\r\n|\n|\r)/gm, "");
responseText = responseText.replace('<?xml version="1.0" encoding="utf-8"?>', '');
responseText = responseText.replace('<string xmlns="http://tempuri.org/">', '');
responseText = responseText.replace('</string>', '');
postMessage("Success");
//updateTable(responseText);
} else {
postMessage("Fail");
//alert("Could not connect to database. Check your internet connection.");
}
var c = 0;
var b = 1;
}
var q=1;
The debugger will just end after the "invocation.send()" line. No error, no status, no nothing. And that's where I'm lost.
Any insight would be greatly appreciated. Also, this exact code works when it is not in a WebWorker, so there's likely something about them that I do not understand.
Thanks in advance!
Chrome problem. Silent fail if COR request is blocked. Firefox console shows more information on the error.

Categories