Is onload equal to readyState==4 in XMLHttpRequest? - javascript

I am confuse about the xhr return event, as I can tell, there are not so much different between onreadystatechange --> readyState == 4 and onload, is it true?
var xhr = new XMLHttpRequest();
xhr.open("Get", url, false);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4)
{
/* do some thing*/
}
};
xhr.send(null);
or
xhr.onload = function() { /* do something */ }

This is almost always true. One significant difference, however, is that the onreadystatechange event handler also gets triggered with readyState==4 in the cases where the onerror handler is usually triggered (typically a network connectivity issue). It gets a status of 0 in this case. I've verified this happens on the latest Chrome, Firefox and IE.
So if you are using onerror and are targeting modern browsers, you should not use onreadystatechange but should use onload instead, which seems to be guaranteed to only be called when the HTTP request has successfully completed (with a real response and status code). Otherwise you may end up getting two event handlers triggered in case of errors (which is how I empirically found out about this special case.)
Here is a link to a Plunker test program I wrote that lets you test different URLs and see the actual sequence of events and readyState values as seen by the JavaScript app in different cases. The JS code is also listed below:
var xhr;
function test(url) {
xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function() { log(xhr, "readystatechange") });
xhr.addEventListener("loadstart", function(ev) { log(xhr, "loadstart", ev.loaded + " of " + ev.total) });
xhr.addEventListener("progress", function(ev) { log(xhr, "progress", ev.loaded + " of " + ev.total) });
xhr.addEventListener("abort", function() { log(xhr, "abort") });
xhr.addEventListener("error", function() { log(xhr, "error") });
xhr.addEventListener("load", function() { log(xhr, "load") });
xhr.addEventListener("timeout", function(ev) { log(xhr, "timeout", ev.loaded + " of " + ev.total) });
xhr.addEventListener("loadend", function(ev) { log(xhr, "loadend", ev.loaded + " of " + ev.total) });
xhr.open("GET", url);
xhr.send();
}
function clearLog() {
document.getElementById('log').innerHTML = '';
}
function logText(msg) {
document.getElementById('log').innerHTML += msg + "<br/>";
}
function log(xhr, evType, info) {
var evInfo = evType;
if (info)
evInfo += " - " + info ;
evInfo += " - readyState: " + xhr.readyState + ", status: " + xhr.status;
logText(evInfo);
}
function selected(radio) {
document.getElementById('url').value = radio.value;
}
function testUrl() {
clearLog();
var url = document.getElementById('url').value;
if (!url)
logText("Please select or type a URL");
else {
logText("++ Testing URL: " + url);
test(url);
}
}
function abort() {
xhr.abort();
}

It should be the same thing. onload was added in XMLHttpRequest 2 whereas onreadystatechange has been around since the original spec.

No, they are not the same. If you encounter a network error or abort the operation, onload will not be called. Actually, the closest event to readyState === 4 would be loadend.
The flow looks like this:
onreadystatechange
readyState === 4
⇓
onload / onerror / onabort
⇓
onloadend

in simple code here how they are handle the error
xhr.onload = function() {
// same or allowed cross origin
if (this.status == 200) {
}
else {} // error http status not 200
};
xhr.onerror = function() {
//error: cross origin, bad connection
};
VS
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (this.status == 200) {
}
else {} // error: cross origin, http status not 200, bad connection
}
};

Related

I need wait for HTTP response

i need to do several readings HTTP, and i need wait for response. But HTTP is async. Then i don't know how.
my code is:
var clientelee = Ti.Network.createHTTPClient({
// function called when the response data is available
onload : function(e) {
Ti.API.info("******* Recibido: " + this.responseText);
},
// function called when an error occurs, including a timeout
onerror : function(e) {
Ti.API.debug("****** ERROR *********"+e.error);
},
onreadystatechange: function(e){
Ti.API.info("******* STATUS *********"+e.readyState);
},
timeout : 3000 // in milliseconds
});
function LeeDatos(){
url = "http://www.hola.com/read/"+leoSerie;
// Prepare the connection.
clientelee.open("GET", url);
// Send the request.
clientelee.send();
}
for (i=0;i<NRegistros;i++){
TablaSerieTermostatos[i]=rows.field(0);
leoSerie=rows.field(0);
LeeDatos();
......
}
Any suggestion?? Thanks
On the callback could you not just pass function and when it's loaded continue with your code.
onload : function(e) {
Ti.API.info("******* Recibido: " + this.responseText);
LoadedData();
},
function LoadedData() {
// Data loaded from ASYNC Carry on...
}
or you could do it this way:
function waitForResponse( type, url, callback ) {
var client = Ti.Network.createHTTPClient({
// function called when the response data is available
onload : function(e) {
Ti.API.info("******* Recibido: " + this.responseText);
callback();
},
// function called when an error occurs, including a timeout
onerror : function(e) {
Ti.API.debug("****** ERROR *********"+e.error);
},
onreadystatechange: function(e){
Ti.API.info("******* STATUS *********"+e.readyState);
},
timeout : 3000 // in milliseconds
});
client.open(type, url);
client.send();
}
function LeeDatos(){
url = "http://www.hola.com/read/"+leoSerie;
waitForResponse( "GET", url, function() {
// Data Ready...
});
}
for (i=0;i<NRegistros;i++){
TablaSerieTermostatos[i]=rows.field(0);
leoSerie=rows.field(0);
LeeDatos();
......
}

Promise does not catch an error

function getJSON(url){
return new Promise(function(resolveFN, crashFN){
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'json';
processing(); //this is for special notifcation appear
request.onload = function(e){
resolveFN(request.response);
removeProcessing(); //this is for special notifcation disappear after 'onload'
};
request.onerror = function(){
debugger; //this is not invoked when url is wrong
crashFN(new Error(' Couldn\'t load at: ' + url));
};
request.send();
});
}
next when I use eventListener - it doesn't catch an error:
var prev = document.getElementById('prev');
prev.addEventListener('click', function(){
getJSON('http://marsweather.ingenology.com/v1/archive/1').then(function(response){
debugger; //this is invoked
console.log(response);
}).catch(function(err){
debugger; // and this is not invoked. why?
console.log('errrrrrrer ', err);
});
});
What could be the reason that catch doesn't work inside the eventListener?
UPDATE: Dmitriy Loskutov suggested this - When should XMLHttpRequest's onerror handler fire
The Promise isn't at fault. You need to check appropriately for the status in your onload handler.
request.onload = function(e){
if (request.status === 200) {
resolveFN(request.response);
}
else {
rejectFN(...);
}
removeProcessing(); //this is for special notifcation disappear after 'onload'
};

XMLHttpRequest readyState stops on 1

I'm having some problems with this code I've done:
function server_status() {
setInterval(function(){
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://mcapi.sweetcode.de/api/v2/?info&ip=jogar.millenarycraft.com', true);
xhr.onreadystatechange = new function(){
document.getElementById("server_counter").innerHTML = 'ReadyState: ' + xhr.readyState;
if (xhr.readyState == 4) {
data = JSON.parse(xhr.responseText);
if(data.status){
document.getElementById("server_counter").innerHTML = '<span>Jogadores online: <span style="color:#FD7C00;">' + data.player.online + '</span></span>';
}else{
document.getElementById("server_counter").innerHTML = '<span style="color:#FD7C00;">Servidor offline!</span>';
}
}
}
xhr.send();
}, 1000);
}
It is inside a script tag and work as well, but I'm having problems just from document.getElementById("server_counter").innerHTML = 'ReadyState: ' + xhr.readyState; on. I noticed that the readystate stops on 1 and I don't know why! Can anyone help me?
PS: And the problem is not with the url, because I did a PHP version and it worked very well. I just want to use JavaScript because I need to update the value without refreshing the page in a certain time.
I think you have an unintended error:
xhr.onreadystatechange = new function(){
Change to:
xhr.onreadystatechange = function(){
new should most certainly not be there. I think as it is your function is called once before you've called xhr.send(), hence xhr.readyState is 1.

Ajax callback function behaving randomly. What have i done wrong?

I have following ajax function that behaves randomly. Sometimes alert success finally is displayed. On other occasions, second alert that is
Failure: my status is 500 is displayed.
promptId is passed on from the calling function. I have checked the prompturl and promptId. A valid value
of promptId is displayed on both occasions (success and failure). Also the audio file that I am trying to play is played in both cases (success and failure).
I can not figure out the cause for this random behavior of alerts being displayed.
If 500 error is coming then it means , resource is not found, but my app is able to access the resource(that is playing the audio file).
function ajax_playPrompt(promptId) {
alert(promptId)
var playPromptUrl = soapUrl + "?action=playPrompt&promptId=" + escape(promptId) + "&parentSessionId=" + parentSessionId;
alert(playPromptUrl);
playPrompt_http_request = getNewHttpRequest('text/plain');
playPrompt_http_request.onreadystatechange = callback_ajax_playPrompt;
playPrompt_http_request.open("GET", playPromptUrl, true);
playPrompt_http_request.send(null);
}
function callback_ajax_playPrompt() {
if (playPrompt_http_request.readyState != 4) {
alert("Returning bcause not 4");
return;
}
if (playPrompt_http_request.status == 200) {
alert("Success finally");
}
else {
alert("Failure:My status is "+playPrompt_http_request.status ); // this gives status as 500
}
}
Also to support different browser I am using:
// to provide support for different browsers.
function getNewHttpRequest(contentType) {
var myRequest;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
myRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
myRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
if (myRequest.overrideMimeType) {
myRequest.overrideMimeType(contentType);
}
return myRequest;
}
Additional Info: I have multiple audio files. When I play an audio file the first time, I get the failure alert first time(even though audio is played), but during if I play it again, second time, success alert is displayed.
Can you try this?
function ajax_playPrompt(promptId) {
alert(promptId)
var playPromptUrl = soapUrl + "?action=playPrompt&promptId=" +
escape(promptId) + "&parentSessionId=" + parentSessionId;
alert(playPromptUrl);
var playPrompt_http_request = getNewHttpRequest('text/plain');
playPrompt_http_request.onreadystatechange = function {
if (playPrompt_http_request.readyState != 4) {
alert("Returning bcause not 4");
return;
}
if (playPrompt_http_request.status == 200) {
alert("Success finally");
} else {
alert("Failure:My status is "+playPrompt_http_request.status );
}
};
playPrompt_http_request.open("GET", playPromptUrl, true);
playPrompt_http_request.send(null);
}

JavaScript settimeout is not working

This script is throwing this error every half second:
Uncaught InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable. signals.js:9
req.onreadystatechange signals.js:9
update_table signals.js:26
req.onreadystatechange
This is signals.js - I want it to reload every 5 seconds and if there is new content, to trigger the "Sound" alert.
function update_table()
{
var old_table = document.getElementById('signals').innerHTML;
var req = new XMLHttpRequest();
req.onreadystatechange = function(){
if(req.status == 200)
{
if(req.readyState == 4)
{
var new_table = req.responseText;
alert(old_table);
alert(new_table);
if(old_table != new_table)
{
//play sound
alert("Sound!");
}
alert("Refresh!");
setTimeout(update_table, 5000);
}
}
}
var link = "table.php?refresh=true";
req.open("GET", link, false);
req.send();
}
First check if the req.readyState equals 4 and then check if the req.status equals 200.
The HTTP status code isn't set before the request is processed, so you can't use it before the readyState equals 4.
You can check this link for more info about the onreadystatechange event.
You need to first check whether req.readyState equals to 4 (means DONE), and only then check for req.status:
function update_table() {
var old_table = document.getElementById('signals').innerHTML;
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
// Here: first check for readyState
if(req.readyState === 4 && req.status == 200) {
var new_table = req.responseText;
alert(old_table);
alert(new_table);
if(old_table != new_table)
{
//play sound
alert("Sound!");
}
alert("Refresh!");
setTimeout(update_table, 5000);
}
}
var link = "table.php?refresh=true";
req.open("GET", link, false);
req.send();
}
See XMLHttpRequest doc for details.

Categories