If statement causes parsing but nothing else inside the branch - javascript

This is an odd one; This function is called by a timer every 1 second in Qt. Check out the if statement; first it parses some JSON data, then it logs that it is parsing. As I would expect, the console.log is only happening when fileshow.txt changes it contents. HOWEVER -- The line that says var parsed = JSON.parse(t) reports a parsing error every 1 second, even when nothing else (including the logging) occurs during that one second:
function get() {
var xhr = new XMLHttpRequest;
xhr.open("GET", "/fileshow.txt");
xhr.onreadystatechange = function () {
var t = xhr.responseText;
if (t != tt.lastData) {
var parsed = JSON.parse(t);
console.log("parsing");
viewer.newImages(parsed.files);
thetime.shouldRepeat = parsed.repeat;
thetime.fps = parsed.fps;
tt.lastData = t;
thetime.running = true;
}
}
xhr.send()
}
Even though I get a parse error (which is a different topic -- the data is in fact parsing correctly despite the error, as it is getting routed via the above formulas just fine and other parts of the program get the data as expected), I should not even be seeing an error for that source code line unless that if branch actually runs! How can it report a parsing error that could only happen in that if branch when that if branch is not even running?!
There is no other parsing anywhere, and the error is reported for the specific line number of this JSON.parse call.

If you're asking why the if statement executes, it's because onreadystatechange is called every time the state of the XHR request changes. There are 5 states for XHR:
0: UNSENT (open() has not been called yet)
1: OPENED (send() has not been called yet)
2: HEADERS_RECEIVED (send() has been called and headers and status are available)
3: LOADING (downloading; responseText holds partial data)
4: DONE (operation complete)
Because onreadystatechange will be called when it starts loading, you're getting passed in a partial JSON file, which is extremely unlikely to validate as proper JSON. You need to check that the readyState is 4, that is, it has finished loading:
if (xhr.readyState === 4 && xhr.status === 200 && t != tt.lastData) {
You also probably want to check that the request was successful by checking for a HTTP 200 response. For more information about XMLHttpRequest, see this MDN article.

Related

How to check XMLHttpPRequest 's unique ID?

I am trying to complete my website request Tamper tool written in JavaScript, However, I am facing my last issue. Below is example function to hook to XMLHttpRequest request. Each request immediately starts with readyState=1, however, only after server returns response, it gets readyState=4.
https://jsfiddle.net/v4mgna51/
However, my problem is that, once in every 1 second, the request is fired, and before it gets response from server, another request might have started in the meanwhile, so making me unable to track (inside readyState==4 ) to check to which initiated call does this "response" corresponds to.
How can I find that out?
The only way I saw was a bit ugly approach (adding uniqueID manually), like this:
this.addEventListener("readystatechange", function(event) {
if(this.readyState == 1){
event.target.uniqueID = Math.floor( (Math.random() * 99999999) + 1 );
}
if(this.readyState == 4){
console.log(event.target.uniqueID);
}
}, false);

Spark POST returns 404 not found seemingly-arbitrarily

Spark has been acting weird lately. I have a button which when clicked calls a POST method with some query parameters:
post("/test", (request, response) -> {
model.put("reason", "some reason here");
...
LOG.info("Returning from /test with reason: " + model.get("reason"));
// the above line always executes and always prints the correct output (never 404)
return new ModelAndView(model, "test.vtl");
}, new VelocityTemplateEngine());
The file test.vtl contains only this: $reason
(which is used in the JS code below to show an alert with the contents of the reason key in the model map).
JS relevant code:
xmlHttp.open("POST", "/test", true);
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var params = "file=" + file + "&searchStr=" + searchStr;
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == XMLHttpRequest.DONE) {
alert(xmlHttp.responseText);
}
}
xmlHttp.send(params);
When I click it, sometimes it work perfectly, and when I click again I get a 404 Not Found with:
MatcherFilter:152 - The requested route [/test] has not been mapped in Spark
This happens in a matter of seconds. I click - it works - I click again if fails - again it fails - again it fails - again it suddenly succeeds...
How can that be?
P.s. I have logging inside the post request, so I know Spark is actually accessing it. But it is not returning from it. Does this perhaps have to do with the code inside the post that suddenly raises the 404 (I am not accessing other pages from it though).
There seem to be 2 possible answers to this (why do they solve is a different question):
Adding a Thread.sleep(250); // or even lower.
Changing the request to GET.
I could not find what is the root cause of these arbitrary failures, but ended up choosing option #2.

Why Chrome sometimes makes 2 AJAX requests instead of 1?

I have encountered a strange behaviour of current version of Google Chrome (44.0.2403.157) on OS X.
When I do AJAX (XHR) request with method GET with my Chrome sometimes makes 1 request and sometimes - 2 (!).
My code:
var jsUrl = 'http://www.some-domain.com/xy.js';
var ajax = new XMLHttpRequest();
ajax.withCredentials = true;
ajax.open( 'GET', jsUrl, true ); // async, because sync cannot be send with cookies
ajax.onreadystatechange = function () {
var script = ajax.response || ajax.responseText;
if (ajax.readyState === 4) {
switch( ajax.status) {
case 200:
case 304:
eval.apply( window, [script] );
// no break on purpose here
default:
someFunction();
}
}
};
ajax.send(null);
A screenshot of my developer console when 2 requests are being made:
Server log confirms that the second request is being made - it's not just in the console.
The headers of the second request are practically the same as the first one - the only difference is the value of the cookie that is being changed with the 3rd request on the screen above.
Note that current version of Firefox (40.0.3) on OS X doesn't show this behaviour - only 1 request is made here, every time (tested by both watching request using Firebug (with BFCache requests shown) and by watching the server logs).
For a while I thought that using send() vs send(null) makes a difference - that when using send() only one request is being made - but after more tests I see that the strangeness is present with both syntaxes.
Can you give me a hint about what is happening here?

AJAX call with common parameters gives always readyState = 1

I'm writing a ColdFusion application that fills with some HTML content some divs once the corresponding button is clicked.
What happens is that the readyState never goes up from the initial state of 1.
The fact that makes me crazy is that I used the same AJAX code in other modules that work fine.
I tried manually the code in my applet "___AJAX_load_translator.cfm" to see if works correctly (inputting a complete url with parameters and query string) and it works.
I put many alerts in these javascript functions to trace if the url was created correctly, the parameters were formatted correctly and so on. Everything seems fine. This is driving me crazy. The result is the same on FireFox and IE.
function getHTTPObject(){
if (window.ActiveXObject) return new ActiveXObject("Microsoft.XMLHTTP");
else
if (window.XMLHttpRequest) return new XMLHttpRequest();
else {
alert("No AJAX support.");
return null;
}
}
function setOutput(divID){
if(httpObject.readyState == 4 && httpObject.status == 200){
document.getElementById(divID).innerHTML = httpObject.responseText;
} // else alert(httpObject.readyState + ' ' + httpObject.status);
}
function loadeditor(divID,CP,PP){
<CFOUTPUT>var CF_TOKENS = "CFID=#CFID#&CFTOKEN=#CFTOKEN#";</CFOUTPUT>
var operativeurl= "___AJAX_load_translator.cfm?"+CF_TOKENS+"&CP="+CP+"&PP="+PP;
httpObject = getHTTPObject();
if (httpObject != null) {
httpObject.open("POST", operativeurl, true);
httpObject.onreadystatechange = setOutput(divID);
httpObject.send(null);
}
}
I noticed that, putting an alert into the setOutput function, it displays a sudden readystate of 1. Then the browser statusbar shows the status of wait for a call to the server, that disappears quite immediately. It seems that the call is really done in that moment, and probably it is imho.
But it seems to me that after that readyness of the call (state 1) there is no more proceeding. It seems somehow blocked. Or, the function setOutput is deactivated. Maybe a second change to a state of 4 happens and this state is not registered by the callback ? In this case, why the DIV is not updated with the new content ?
Thanks for any help.
httpObject.onreadystatechange = setOutput(divID);
^^^^^^^
You're calling/executing your setouput function right then and there, and whatever the function returns becomes on the onreadystatechange callback "pointer".
Remove the (divID) portion, so you assign the function itself, not whatever it returns:
httpObject.onreadystatechange = setOutput;

onreadystatechange in a loop, readystate changes too late

I issue in a loop a total of eight xmlhttprequests to a Google map server and process the json objects the server returns to retrieve the zip codes. The code works fine if the xmlhttprequests are synchronous. Since I'm supposed to use asynchronous requests, I'm trying to convert the code to asynchronous. It doesn't work.
I use two alerts to monitor myZip. When the code is run, the second alert, right above the return, runs eight times and shows myZip as null or undefined and that is what is returned. Then the first alert runs eight times and gives the desired zip code, too late, unfortunately. It seems to me the readystate doesn't change until too late.
How should I modify the code so it will return the zip code, not null? Any help will be greatly appreciated.
var url = "http://maps.googleapis.com/maps/api/geocode/json?address="+address+city+state+"&sensor=false";
req.open("GET", url,true);
var myZip;
req.onreadystatechange = function()
{
if(req.readyState == 4 && req.status == 200) {
(function(data){
var myObj = eval( '(' + data + ')' );
if(myObj.status=="OK"){
for(i=0; i <myObj.results[0].address_components.length; i++){
if(myObj.results[0].address_components[i].types=="postal_code"){
myZip=myObj.results[0].address_components[i].long_name;
alert('zip is '+myZip);
}
}
}
else
{
alert("Error: returned status code "+req.status+" "+req.statusText);
}
})(req.responseText);
}
}
req.send();
alert(myZip);
return myZip;
You should either use a callback instead of return statement, or you should run this as Stratified JavaScript: http://stratifiedjs.org.
Then you can write it in a synchronous fashion, like you kind of did, even though it will NOT block your browser.
I guess you use the same object(req) a couple of times and will be overwritten on each loop.
So use separate objects for every requests or start a new request if the last one is finished.
How exactly you can do this I cannot say without knowing what req is.

Categories

Resources