execute javascript before XML Request - javascript

I'm not very used to xml requests, but is there a way to execute code before a XMLHttpRequest. What I'm trying to do is, Send a request and open a new url. But since this takes a few seconds and I got a few requests at once, I want a loading screen to appear while sending requests. Here is my code so far:
function sendRequests(){
url = "placeholder";
url2 = "placeholder2";
displayObject("loadingScreen");
var xmlHttpCart = new XMLHttpRequest();
xmlHttpCart.open( "GET", url, true );
xmlHttpCart.send( null );
window.open(url2,"_self");
}
function displayObject(i) {
var id = "" + i;
document.getElementById(i).style.display = "inherit";
}
Unfortunately the displayObject() function is triggered after the request is finished.
thanks

The browser will finish running the JavaScript until it finishes whatever it is doing. This blocks repainting the display.
xmlHttpCart.open( "GET", url, false ); // false for synchronous request
This is one example of why using false there is deprecated and you should not do that.

Related

Pass the value of an xhr onload function globally

In an app I'm creating I have the below XMLHttpRequest and I'm trying to pass the results of data inside the xhr.onload() into an array that's created within the same parent function.
var url = 'http://api.soundcloud.com/resolve.json?'+resource+'&'+CLIENT_ID;
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function(){
var data = JSON.parse(xhr.responseText);
console.log(data.permalink_url);
};
xhr.send();
Below this I have the building blocks of an array and I'm trying to pass the results of data into the track string.
var metadata = {
id: val,
title: title,
url: posturl,
track: data.permalink_url
};
Everything I've tried thus far either returns undefined or function and now I'm totally out of ideas...
Ajax executes asynchronously (generally). This is vital to how Ajax works. What this means is that you can't count on the when the onload method will fire, or even if it will fire. What this means is that all code that depends on the xhr.responseText (result of the HTTP request) has to be done within the callback itself. For example:
xhr.onload = function () {
// This will execute second
doStuffWithData(JSON.parse(xhr.responseText));
}
// This will execute first
xhr.send();
var anything = anythingElse;
Like I said in the comment to my previous answer, you can change the one line to xhr.open('GET', url, false). It will make the request synchronous and will prevent everything else from running until the request completes. It will allow you to access xhr.responseText without waiting for an onload function.
CLIENT_ID = 'client_id=xxx';
var src = track,
match = src.match(/url=([^&]*)/),
resource = match[0],
stream = decodeURIComponent(match[1]) + '/stream/?' + '&' + CLIENT_ID;
var url = 'http://api.soundcloud.com/resolve.json?' + resource + '&' + CLIENT_ID;
var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.send();
parsedResults.push({
title: title,
track: JSON.parse(xhr.responseText)
});
You can see it in action here. It appears to be broken in Chrome for some reason. Works in Firefox though. I assume it's something to do with the CORS + 302 redirect + synchronous request.
I've gone for Explosion Pills solution. The only problem I encounter is that the links that get crawled don't always come back in the same order each time I run the node app. Realistically they should return in the order that they're crawled in (which would be newest posts first, right?) However this isn't always the case?

Asynchronous ajax call blocking UI

Once the JSP is rendered, I'm here trying to make an Asynchronous call via ajax to load additional information on the page.
I'm expecting that ajax load to happen gracefully without hampering the UI scroll bar navigation. But the call blocks the UI until the onLoad is complete.
At other times, this service blocks UI even on a mouse click ajax call (the cursor remains as pointer type until data is loaded).
In both cases, I'm building DOM via javascript (like creating innerHTMl for a div or table). Is it because of this? or something else? I'm attaching my ajax request code.
Appreciate your help. (Sorry, I tried to format the code, but I'm unable to get it right here)
function requestService(theService, theParamObj, isSyncCall) {
var ajaxRequest = getAjaxRequest();
var params = "data=";
if(theParamObj != null)
params += encodeURIComponent(JSON.stringify(theParamObj));
ajaxRequest.onreadystatechange = function() {
if (ajaxRequest.readyState == 1) {
showLoadingBox();
}
if (ajaxRequest.readyState == 4) {
handleResponse(ajaxRequest.responseText, theService, theParamObj);
hideLoadingBox();
}
};
var queryString = "?timestamp=" + new Date().getMilliseconds() + "&theService=" + theService;
if(isSyncCall == null)
isSyncCall = false;
ajaxRequest.open("POST", g_Service + queryString, isSyncCall);
ajaxRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajaxRequest.send(params);
}
Update:
onLoad call to this service
function loadAdInfo(){
var theParamObj = {"REQUEST_URI" : window.location.href};
requestService('getAdInfo', theParamObj, false);
}
The XMLHTTPObject open method is defined like this:
open(method,url,async) Specifies the type of request, the URL, and if the request should be handled asynchronously or not.
method: the type of request: GET or POST
url: the location of the file on the server
async: true (asynchronous) or false (synchronous)
You are passing false. so you are calling it synch

How to invoke a "Please Wait" window only if ajax takes more than X milliseconds to respond?

I'm doing an AJAX call (regular JS) and, if it takes more than, say, 500 milliseconds, I'd like to put up my "Please Wait" box.
Normally, if I want to put up the PW box immediately, I'd do:
// show semi-transparent grey screen to block access to everything underneath
divGreyCoverAllNode.style.display = 'inline';
// show PW box. Prior to these lines, both coverall and PW were display=none
divPleaseWaitNode.style.display = 'inline';
// now do the AJAX and follow-up inside a zero timer; the timer is necessary to
// make the system pause to display the screen changes we previously invoked
setTimeout( function() {
// do my ajax call here, then after the call...
// take down the PW stuff
divPleaseWaitNode.style.display = 'none';
divGreyCoverAllNode.style.display = 'none';
},
0
);
Like I stated above, what I'd like to do is have the PW displayed only if AJAX doesn't finish in, say, 500 milliseconds. Ideally it would be something like:
// set a timer to display PW in 500 milliseconds
myTimeEvent = setTimeout( function() {
divGreyCoverAllNode.style.display = 'inline';
divPleaseWaitNode.style.display = 'inline';
},
500
);
// do my ajax call here, then after the call...
clearTimeout(myTimeEvent);
// take down the PW stuff, in case it was displayed
divPleaseWaitNode.style.display = 'none';
divGreyCoverAllNode.style.display = 'none';
But I can't seem to get the system to pause and display the PW when AJAX is taking its time. I've tried surrounding the AJAX-and-follow-up block in a zero timer, but no deal.
Any suggestions?
EDIT:
Important fact: This is not an asynch ajax call. It's an unusual situation that requires everything to wait on the ajax result.
Given that you are making a synchronous XHR call, you can't. That's the nature of synchronous – everything stops until the call completes. When you use a synchronous XHR request, not only is the JavaScript event loop stopped, you actually freeze the entire browser UI (in IE and Firefox < 3).
That said, you're doing it wrong. 8.4% of reported IE9 hangs last month were due to synchronous XHR. There really is no such thing as β€˜an unusual situation that requires use of synchronous XHR requests.’ Make your request, then act on the data you get in the callback function.
Instead of something like:
// Do stuff, then when you need a request:
var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.send();
// Do more stuff
alert(xhr.responseText);
You need:
// AJAX helper
function req(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) callback(xhr);
}
}
// Your code. Do stuff, then when you need an AJAX request:
req(url, function(xhr) {
// Do more stuff
alert(xhr.responseText);
});
Obviously this needs refined, but this illustrates the proper way to make an AJAX request.
It shouldn't come after the ajax call, it should come inside the callback function. AJAX requests are asynchronous with the rest of the code, you should preform actions you want upon completion inside the callback part of your request.
take a look at BlockUi. If that doesn't look like it will work for you, you could try using
$(document).ajaxStop(DoSomething());
Take a Look at jQuery Timeout

Javascript: xmlhttprequest randomly stuck at Ready State 1

I've been working on a Windows gadget (meaning the "browser" is Internet Explorer) that queries specified subnet addresses for information. Now, it sometimes does this at a relatively quick pace (roughly every 5 seconds) and it works well enough. However, sometimes it will get stuck at ready state 1 and will just stay there forever. Whenever the gadget tries to redo the function for getting the xmlhttprequest and getting information from it it will stay at state 1. This is easily replicable when opening multiple instances of the gadget and then closing all but one of them. At that point, the one that's still open will almost always get stuck in this state. I feel like it might have something to do with them all accessing the same website, or it may just have to do with xmlhttprequests being stopped mid-transmission and that preventing another from working. Below is the relevant code.
//Reference to this for the inner function
var me = this;
var request = new XMLHttpRequest();
request.onreadystatechange = onReadyStateChange;
var url = this.url;
//Make the URL random to prevent being cached
url += ("&a=" + ((new Date()).getTime()));
Trace(DEBUG_COMM, "Sase.updateStatus url: " + url);
request.open("GET", url, true);
request.send(); // fire off the request, calls httpRequestReadyStateChange as things continue
Trace(DEBUG_COMM, "Request sent" + request.readyState);
function onReadyStateChange() {Trace(DEBUG_COMM, "Sase.httpRequestReadyStateChange: state=" + request.readyState);
if (4 == request.readyState) {
Trace(DEBUG_COMM, "Sase.httpRequestReadyStateChange: status=" + request.status);
if (request.status == 200) {
Trace(DEBUG_COMM, "retrieved html: " + request.responseText);
var results = request.responseText;
var resultsString = request.responseText.toString();
Trace(DEBUG_COMM, "results String: " + resultsString);
me.ParseStatusData(resultsString);
}
else {
//me.commError(request.status);
}
request = null;
}
}
Well it looks like I figured it out. I had a feeling it was an unresolved request, since it only happens when instances of it are closed (meaning that if one of them is closed while in communication with the server it stays in communication forever and no one else can access the server) and it appears that is the case. I made some modifications to the code in multiple areas and basically what it comes down to is when the gadget closes it makes sure to abort all of the requests. The requests are now instance variables (to allow for the aborting of them), but are still made new everytime they are needed.
For those who stumble across this and need a concrete code example, here you go.
I had the same problem and the solution was to re-use the XMLHttpRequest object, to ensure that any previous request was cancelled before initiating a new one. This won't work if you want to have multiple AJAX requests flying around but in my case triggering a new request meant that the last one was no longer needed.
All of the requests on my page went through the same XMLHttpRequest wrapper method which looked like this;
//Declare the XMLHttpRequest object to be re-used
var global_xHttpRequest = null;
function xmlHttpHandler(type, params, complete, postData) {
//Prevents an issue where previous requests get stuck and new ones then fail
if (global_xHttpRequest == null) {
global_xHttpRequest = new XMLHttpRequest();
} else {
global_xHttpRequest.abort();
}
//Parse out current URL
var baseURL = window.location.host;
var svc = "https://" + baseURL + "/processAction?";
var url = svc + params;
global_xHttpRequest.open(type, url, true);
//Add the callback
global_xHttpRequest.onreadystatechange = complete;
global_xHttpRequest.send(postData);
}
Which can be used like this:
xmlHttpHandler("GET", params, completeFnc);

How to implement a getter-function (using callbacks)

I have to request data for a JS-script from a MySQL database (based upon a user-id).
I did not find a simple solution for JavaScript and it was not possible to load the data using ajax, because the database is available under a different domain.
I implemented a workaround using PHP and curl.
Now the JS has to "wait" for the request to finish, but the script is of course running asynchronously and does not wait for the response.
I know that it's not really possible to wait in JS, but it must be possible to return value like this.
I also tried using a return as another callback, but that didn't work of course, because the getter-function will run further anyway.
How can I implement a simple getter, which "waits" and returns the response from the HTTP-request?
Thanks for any other clues. I'm really lost at the moment.
This is a excerpt from the source code:
/**
* Simple getter which requests external data
*/
function simple_getter() {
// http request using a php script, because ajax won't work crossdomain
// this request takes some time. function finished before request is done.
/* Example */
var url = "http://example-url.com/get_data.php?uid=1234";
var response_callback = handle_result_response;
var value = send_request( url, response_callback );
value = value.split('*')[0];
if (value === '' || value == const_pref_none) {
return false;
}
/* 1. returns undefinied, because value is not yet set.
2. this as a callback makes no sense, because this function
will run asynchronous anyway. */
return value;
}
Additional information about the used functions:
/**
* Callback for the send_request function.
* basically returns only the responseText (string)
*/
function handle_result_response(req) {
// do something more, but basically:
return req.responseText;
}
/**
* Requests data from a database (different domain) via a PHP script
*/
function send_request( url, response_callback ) {
var req = createXMLHTTPObject();
if (!req)
return;
var method = (postData) ? "POST" : "GET";
req.open(method, url, true);
req.setRequestHeader('User-Agent','XMLHTTP/1.0');
// More not relevant source code
// ...
req.onreadystatechange = function () {
// More not relevant source code
// ...
response_callback(req);
}
if (req.readyState == 4)
return;
req.send(postData);
}
Not really relevant code, but required for the HTTP-request:
var XMLHttpFactories = [
function () {return new XMLHttpRequest()},
function () {return new ActiveXObject("Msxml2.XMLHTTP")},
function () {return new ActiveXObject("Msxml3.XMLHTTP")},
function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];
function createXMLHTTPObject() {
var xmlhttp = false;
for (var i=0; i<XMLHttpFactories.length; i++) {
try {
xmlhttp = XMLHttpFactories[i]();
} catch (e) {
continue;
}
break;
}
return xmlhttp;
}
You really, really shouldn't try to synchronously wait for a network request to complete. The request may never complete, may hang and take a long time, and so on. Since JavaScript is single threaded, and in fact all major browser engines are single threaded, this will cause your entire page to hang while waiting for the request, and in some browsers, may cause the entire browser to hang.
What you should do is replace code like this:
var returned = some_request('http://example.com/query');
do_something_with(returned);
with code like this:
some_request('http://example.com/query', function (returned) {
do_something_with(returned);
});
That way, you will never cause your page or the browser to hang waiting for the request, and can simply do the work once the response comes in.
I don't see whats wrong with your code in general.
When you make a request, provide a Callback. When a response comes back, which you can easily detect, execute the Callback and pass it the result.
This is the way client side apps work.It is not procedural, but works by events.
You present the screen to the user and wait
The user makes an action
You call the server, set a callback and wait
The response come and you execute the callback and wait for another step 2
Rather than trying to change that, you need to fit with that or it will be a painful experience.
Javascript is not multithreaded. It means a single statement is run at a time. The real asynchronism come from the time the server takes to respond and call the callback. You never know which call will come first and need to build your program with that in mind.

Categories

Resources