I am using the following JavaScript function object to handle requests to the server:
function Request(query, url) {
var that = this;
this.request = new XMLHttpRequest();
this.response = '';
this.set_response = function() {
if (that.request.readyState==4 && that.request.status==200) {
that.response = that.request.response;
}
}
this.request.onreadystatechange = this.set_response;
this.request.open('POST', url, false);
this.request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
this.request.send(query);
}
With this object I can do something like:
var needed_data = new Request('data=needed', 'serverside.php').response;
Now the data I needed from the server is stored nicely in the needed_data variable (as a json encoded string).The problem is using a synchronous request in the main thread has been deprecated. I was hoping someone could help me figure out a way to achieve the same result whilst being standards compliant.
You will have to make it asynchronous.
//allow to pass a callback
function Request(query, url, callback) {
var that = this;
this.request = new XMLHttpRequest();
this.response = '';
this.set_response = function() {
if (that.request.readyState==4 && that.request.status==200) {
that.response = that.request.response;
callback && callback(that); //invoke the callback when data is available
}
}
this.request.onreadystatechange = this.set_response;
this.request.open('POST', url, true); //make the call async
this.request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
this.request.send(query);
}
new Request('data=needed', 'serverside.php', function (request) {
console.log(request.response);
});
You should never be using a synchronous XMLHttpRequest in the same thread as the rest of your application.
function request(query, url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onreadystatechange = function(){
if (xhr.readyState === 4 && xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
xhr.send(query);
return xhr;
}
request('data=needed', 'serverside.php', function(responseText){
var needed_data = JSON.parse(responseText);
});
Related
I'm following a simple book and It says:
function createRequest()
{
try
{
request = new XMLHttpRequest();
}
catch (tryMS)
{
try
{
request = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (otherMS)
{
try
{
request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (failed)
{
request = null;
}
}
}
return request;
}
function getDetails(itemName)
{
var request = createRequest();
if (request==null)
{ alert("Unable to create request");
return;
}
var url= "getDetails.php?ImageID=" + escape(itemName);
request.open("GET",url,true);
request.onreadystatechange = displayDetails;
request.send(null);
}
function displayDetails()
{
if (request.readyState == 4)
{
if (request.status == 200)
{
detailDiv = document.getElementById("description");
detailDiv.innerHTML = request.responseText;
}
}
}
And all this code above is fine and it's okay to me.. but after few pages it says:
ITS VERY IMPORTANT TO REMOVE VAR KEYWORD BEFORE request VARIABLE so the callback can reference the variable...
but how come in example above it worked? is it coincidence if we call a variable 'request' that it will map with global variable in a createRequest method?
Take a look on image below:
Why is this happening ? in one example var before request variable is used and everything is fine, in another var is avoided so the method in callback might access it.. but how come method in a callback is accessing a request variable in first example...
It's confusing because there are 2 similar examples, with different explanations..
EDIT
P.S it says request has to be a global ? :o
Thanks guys
Cheers
In both examples, implicit global variables are created so they can be shared with the callback.
When the second request variable is created, it creates a local variable inside the getDetails function. So when createRequest() returns the global variable, the local variable becomes a reference to it.
This is rather bad advice and shows a lack of understanding on the writers' part. But it seems to be an old text, since activeX objects are deprecated by now, so maybe globals used to be less frowned upon. The proper way is to either send the responseText or responseXML as a parameter to the callback or send the entire request as the parameter for the callback.
Maybe the writer didn't want to make the request code more complex, but imho, this is not a good way to teach people things.
function createRequest( method, url, callback, payload ) {
var request = new XMLHttpRequest();
if ( !request ) {
alert( "Unable to create request" );
return null;
}
request.open( method, url );
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200 ) {
callback( request.responseText );
}
};
request.send( payload );
};
function getDetails( itemName, callback ) {
createRequest( "GET", "getDetails.php?ImageID=" + escape(itemName), callback, null );
};
function displayDetails( detail ) {
var detailDiv = document.getElementById("description");
detailDiv.innerHTML = detail;
};
getDetails( "someItemName", displayDetails );
you are right, in your first example, function createRequest is not using var, which mean you are creating a global variable request when excute request = new XMLHttpRequest();.
We should avoid using gobal var in most situation.
function createRequest() {
try {
// add var so it's not global variable
var request = new XMLHttpRequest();
} catch (tryMS) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (otherMS) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = null;
}
}
}
return request;
}
function getDetails(itemName)
{
var request = createRequest();
if (request==null)
{ alert("Unable to create request");
return;
}
var url= "getDetails.php?ImageID=" + escape(itemName);
request.open("GET",url,true);
// create anonymous function to call your callback and pass `request` as local variable
request.onreadystatechange = function(){
displayDetails(request);
};
request.send(null);
}
function displayDetails(request)
{
if (request.readyState == 4)
{
if (request.status == 200)
{
detailDiv = document.getElementById("description");
detailDiv.innerHTML = request.responseText;
}
}
}
I have a problem getting data from this two sites:
http://app.lotto.pl/wyniki/?type=dl
and
Eurolottery.
I know that the problem is associated with CORS and I managed to get data using Chrome CORS extension and that code:
var HttpClient = function() {
this.get = function(aUrl, aCallback) {
var anHttpRequest = new XMLHttpRequest();
anHttpRequest.onreadystatechange = function() {
if (anHttpRequest.readyState == 4 && anHttpRequest.status == 200)
aCallback(anHttpRequest.responseText);
}
anHttpRequest.open( "GET", aUrl, true );
anHttpRequest.send( null );
}
}
var client = new HttpClient();
client.get('http://app.lotto.pl/wyniki/?type=dl', function(response) {
var currentDraw = response;
x = currentDraw.split("\n").slice(1, 7).sort().join(" ");
console.log(x);
}
);
And I tried to use CORS tutorial code with that:
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// XHR for Chrome/Firefox/Opera/Safari.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// XDomainRequest for IE.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// CORS not supported.
xhr = null;
}
return xhr;
}
// Helper method to parse the title tag from the response.
function getTitle(text) {
return text.match('<title>(.*)?</title>');
}
// Make the actual CORS request.
function makeCorsRequest() {
// This is a sample server that supports CORS.
var url = 'http://api.bentasker.co.uk/lottopredict/?action=LatestResults&key=751fbf6ddfb7c3857d898c21bfdc2b22&game=3&draws=Any';
var xhr = createCORSRequest('GET', url);
if (!xhr) {
alert('CORS not supported');
return;
}
// Response handlers.
xhr.onload = function() {
var text = xhr.responseText;
var title = getTitle(text);
console.log(text.split("\n"));
};
xhr.onerror = function() {
alert('Woops, there was an error making the request.');
};
xhr.send();
}
makeCorsRequest();
But in both situations it doesn't work properly.
What is the easiest way to get data from sites posted above using javascript?
If you don't have control to the Host, you will need to use a proxy (ie: CORS-Anywhere) to remove the CORS policy.
var HttpClient = function() {
this.get = function(aUrl, aCallback) {
var anHttpRequest = new XMLHttpRequest();
anHttpRequest.onreadystatechange = function() {
if (anHttpRequest.readyState == 4 && anHttpRequest.status == 200)
aCallback(anHttpRequest.responseText);
}
anHttpRequest.open( "GET", aUrl, true );
anHttpRequest.send( null );
}
}
var client = new HttpClient();
client.get('https://cors-anywhere.herokuapp.com/http://app.lotto.pl/wyniki/?type=dl', function(response) {
var currentDraw = response;
x = currentDraw.split("\n").slice(1, 7).sort().join(" ");
console.log(x);
}
);
More ways to handle the CORS Policy locally are available here.
If you don't want to setup your own server you could use something like https://cors-anywhere.herokuapp.com/ - it works pretty well for simple cases.
I hope someone can help me, because i can't get it to work and it's really frustrating.
I have the following code
var getJSON = (url, callback) => {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
callback(xhr.response);
}
};
xhr.send();
};
I want to use it to get a json object from the given url but inside the function I want to use the response to get another json object back.
var func1 = (url) => {
getJSON(url, (data) => {
//Do smth here with the data and then for example
func2('https://someurl.com/api/somefunction/' + data.smth.age);
});
}
Now the problem is that in func2 the data will be null or undefinded and it doesn't work after that.
In addition I have more than 2 functions which try to call getJSON.
I hope someone has a solution.
var address = [ "data/somedata1.json", "data/somedata2.json", "data/somedata3.json", "data/somedata4.json", "data/somedata5.json"];
and function to import this file
function readData()
{
var loadFile = function (filePath, done)
{
var xhr = new XMLHttpRequest();
xhr.open("GET", filePath, true);
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.onload = function () { return done(this.responseText) }
xhr.send();
}
address.forEach(function (file, i)
{
loadFile(file, function (responseText)
{
jsonData[i] = JSON.parse(responseText);
if(i === 4)
{
fill(jsonData);
document.getElementById("el").innerHTML = jsonData[2].title3;
Dosometing(jsonData[0])
}
})
})
}
All JSON files have absolute 150kb. Problem is, sometimes when I run this code on website I get jsonData[0] undefinded and sometimes all load success. It means all data are not load properly. What im doing wrong ? There is any chance to write this code better to make sure all files are loaded properly ?
One issue is that even for small files it is not guaranteed, that the downloads finish in order.
It would be better to keep track of the finished download count with a separate variable:
function readData() {
var loadFile = function(filePath, done) {
var xhr = new XMLHttpRequest();
xhr.open("GET", filePath, true);
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.onload = function() { return done(this.responseText) }
xhr.send();
}
var finishedCount = 0;
address.forEach(function(file, i) {
loadFile(file, function(responseText) {
jsonData[i] = JSON.parse(responseText);
finishedCount++;
if(finishedCount === address.length) {
fill(jsonData[4]);
document.getElementById("el").innerHTML = jsonData[2].title3;
Dosometing(jsonData[0])
}
});
})
}
I'm trying to return a json object following an XMLHttpRequest get request, and I come up short. I think that might be because it is asynchronous, but I really can't put my finger on how to make it work. What am I doing wrong?
$(document).ready(function() {
var apiEndpoint = 'http://someapiendpoint.com/'
//Helpers
function sendRequest(_path) {
var results = {}
req = new XMLHttpRequest()
req.open('GET', apiEndpoint+_path)
req.onreadystatechange = function() {
if (this.readyState === 4) {
results = JSON.parse(this.response)
}
}
req.send()
return results
}
// Action
console.log(sendRequest('client1/'))
}); // end document ready
You should use this construction
function sendRequest(_path, cb) {
req = new XMLHttpRequest()
req.open('GET', apiEndpoint+_path);
req.onreadystatechange = function() {
if (this.readyState === 4) {
cb(JSON.parse(this.response));
}
else{
cb(null);
}
}
req.send();
}
// Action
sendRequest('client1/', function(result){
console.log(result);
})
For asynchronous calls you need to use call backs
Since you are already using jQuery you can do the following:
$(document).ready(function() {
var apiEndpoint = 'http://someapiendpoint.com/';
function sendRequest(path, callback){
$.get(apiEndpoint+path, function(response){
callback(JSON.parse(response));
}, json).fail(function(){
console.log('Failed');
});
}
sendRequest('client1/', function(json){
if(json){
console.log(json);
}
});
});