In the XMLHttpRequest Spec it says that:
The DONE state has an associated error
flag that indicates some type of
network error or abortion. It can be
either true or false and has an
initial value of false.
Also says something similar about a "send() flag" in an "OPENED" state.
It's said in the specification but not in the IDL and when I create a new XMLHttpRequest I can't find those "flags".
Where are those boolean variables?
The XMLHttpRequest.readyState property is what you're looking for.
From the Spec you've given, you will see that all those "boolean" flags are actually numeric values.
UNSENT (numeric 0)
OPENED (numeric 1)
HEADERS_RECEIVED (numeric 2)
LOADING (numeric 3)
DONE (numeric 4)
These values are the result of XMLHttpRequest.onreadystatechange event handler.
Basically, in order to get those values, do something of this effect.
//In Javascript
var request = new XMLHttpRequest();
if (request) {
request.onreadystatechange = function() {
if (request.readyState == 4) { //Numeric 4 means DONE
}
};
request.open("GET", URL + variables, true); //(true means asynchronous call, false otherwise)
request.send(""); //The function that executes sends your request to server using the XMLHttpRequest.
}
Bear in mind, always write the onreadystatechange event BEFORE calling the XMLHttpRequest.send() method (if you decide to do asynchronous calls). Also, asynchronous calls will call XMLHttpRequest.onreadystatechange event listener so it's always vital you have that implemented.
More info on Wikipedia
I've heard that the XHR editor said that the error flag referenced in the spec is an internal implementation variable that consumers cannot access.
Same deal with the "send()" flag.
I wrote to the webapps e-mail list about those flags, this is what they responded:
Everything that authors can use is
expressed in the Web IDL fragment.
Everything outside of that represents
some kind of data implementations need
to keep around one way or another to
properly implement the specification.
(That was my doubt)
Related
I use Delphi XE7. When my Javascript calls my server function that need around 800ms to read sensor and return data, The browser is unresponsive from the moment I click the button to invoke the Javascript until it finally response returns. I'm using the default Javascript generated by the proxy var serverMethods().getChannel(i); to call into my server function.
Javascript call look like this:
var s = serverMethods().getChannel(i);
serial[i].$sensorlValue.text(s.result.fields.sensorString);
serial[i].$sensorlRealValue.text(s.result.fields.sensor);
serial[i].$sensorStatus.text(s.result.fields.sensorStatus+' '+s.result.fields.name);
serial[i].$sensorError.text(s.result.fields.sensorError);
serial[i].$AVString.text(s.result.fields.AVString);
serial[i].$AVError.text(s.result.fields.AVError);
So by default example there are no Javascript callbacks or promise, so embaracaderom manage somehow to block Javascript from executing until response is back and variable a receive values?
I think about try using jQuery Ajax call on URL, but is there any other solution?
Because serverMethods are generated from proxy but for $ajax I need to manually set each of them. Or maybe I do something wrong here and serverMethods can be used without blocking ?
Thanks.
I found the solution to this problem after researching execution path in ServerFunctionExecutor.js that is called on serverMethods().SOMEAPIFUNCTION()
1. Help and documentation are 0, and google + XE7 questions are 0. So if someone from embaracadero read this PLS MAKE DECENT DOCUMENTATION.
ServerFunctionExecutor.js had on line 263
//async is only true if there is a callback that can be notified on completion
var useCallback = (callback != null);
request.open(requestType, url, useCallback);
if (useCallback)
{
request.onreadystatechange = function() {
if (request.readyState == 4)
{
//the callback will be notified the execution finished even if there is no expected result
JSONResult = hasResult ? parseHTTPResponse(request) : null;
callback(JSONResult, request.status, owner);
}
};
}
So it is posible and NOT DOCUMENTED to use callback for unblocking GUI.
Use it as:
serverMethods().SOMEAPIFUNCTION(par1,par2,.... callback)
If you have Server method defined in delphi code with for example 3 parameters in js 4th parameter is callback:
For this example code now look like this:
serverMethods().getChannel(i,function(a,b,c){
serial.$sensorlValue.text(a.result[0].fields.sensorString);
serial.$sensorlRealValue.text(a.result[0].fields.sensor);
serial.$sensorStatus.text(a.result[0].fields.sensorStatus+' '+s.result.fields.name);
serial[i].$sensorError.text(a.result[0].fields.sensorError);
serial[i].$AVString.text(a.result[0].fields.AVString);
serial[i].$AVError.text(a.result[0].fields.AVError);
});
a is JSON reponse
b is Request status as number 200 or somethin else
c is owner usuali undefined
I am new to Ajax, and to make things worse, also a Javascript noob, and I have posted the bellow code of a chat script, to retrieve text from db, in real time, and the code is working, but I need to understand what certain requests are all about.
<script>
function retrieve(){
var xmlhttp;
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest(); }
else if(window.ActiveXObject) {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
else {
alert('Please update your browser to start chatting');
}
Simply, I understand the above is (I created it) just a function with global variable declared to be assigned whether XMLHttpRequest/ActiveXObject Object is declared depending if browser is IE6,7 and others if not throw in alert...
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
document.getElementById("canvas").innerHTML = xmlhttp.responseText;
}
}
Similarly, the above I assume takes the onreadystatechange property of the Ajax API and checks for it's state, readyState & status which, if only they match 4 and 200 means, Ajax is working as wanted
t = setTimeout("retrieve()", 2000);
I know the setTimeout() is a bit like setInterval() function, which runs the function inside it, every 2 seconds, to check for new messages.
xmlhttp.open("GET", "getajax.php", true);
xmlhttp.send();
Now, the problem is with the above, I can almost understand that the .open method is supposed to get data from getajax.php even though, I have no idea of what true means in this instance, but as far as the xmlhttp.send(); I have absolutely no clue,
So, All I need is for you to explain to me what I have missed during my illaboration, and
what the last queries mean, just in brief.
}
retrieve();
</script>
<div id="canvas"></div>
xmlhttp.open("GET", "getajax.php", true);
xmlhttp.send();
true is what tells the request to be performed A -synchronously, which is the A in AJAX. Then finally .send() actually send the request.
Asynchronous requests are non-blocking meaning that the rest of your code wont wait for them to finish and return before continuing. That is why you sent event handlers before starting the request via xmlhttp.onreadystatechange. That way once the request is complete you have already told your script what to do with the returned information.
Hope this helps.
Edit Additionally I recommend using some sort of framework or library for javascript like jQuery. While it is good to learn some of the javascript core, something like jQuery will make your life much easier.
Simply, I understand the above is (I created it) just a function with global variable declared to be assigned
xmlhttp isn't a global. It's a local variable in the global function retrieve.
Similarly, the above I assume takes the onreadystatechange property of the Ajax API and checks for it's state
onreadystatechange is a property that accepts a function. That function is run when the value of readyState changes. That function is usually used to check the status of the request.
I know the setTimeout() is a bit like setInterval() function, which runs the function inside it, every 2 seconds, to check for new messages.
setTimeout is like setInterval in a sense that it runs a function at a later time. Unlike setInterval, it only runs the code once. Also, that's not the proper way of running a timer. Here's a post that explains how to properly use timers.
the .open method is supposed to get data from getajax.php even though, I have no idea of what true means in this instance, but as far as the xmlhttp.send(); I have absolutely no clue
The open builds your request by accepting:
The type of request (GET/POST)
The url where you want the request sent
The third argument determines if the request is asynchronous or not.
If set to false, this makes the request synchronous. The browser will freeze and wait for the response.
If true, the request us asynchronous. The browser will not freeze in waiting.
The default value is true, so you can omit it.
send is the actual function that ultimately sends the request to the server.
For further reading, I suggest you read MDN's section regarding AJAX.
I'm learning Ajax and I'm going through this example. What does this do? I don't understand the syntax variable = function(){ how is a function being assigned to a variable?
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
}
}
I know everyone is saying it's a callback specifically but the question you asked could better be answered by comparing what you're puzzled over with some more familiar code.
function myFunction()
{
...
}
So we know that calling myFunction() will run that code.
In Javascript, you can declare a function in a number of ways. This means that this:
var myFunction = function()
{
...
}
Does exactly the same as the first example above. It creates a function that you can call using myFunction().
Add the callback into the mix in your question and we can see that
xmlhttp.onreadystatechange = function()
{
...
}
is nothing more than assigning a function and containing code to the onreadystatechange property of object xmlhttp. Meaning that your code within the function will be called every time there is a state change in the xmlhttp object.
When readyState changes, if request finished and response is ready (readyState==4) and document loaded correctly (HTTP Status Code 200 = OK!), append response text to the element with id #txtHint.
onreadystatechange stores a function (or the name of a function) to be called automatically each time the readyState property changes.
readyState holds the status of the XMLHttpRequest. Changes from 0 to 4:
0: request not initialized
1: server connection established
2: request received
3: processing request
4: request finished and response is ready
status takes HTTP response codes:
200: "OK"
404: Page not found
onreadystatechange is a callback. It gets triggered when a particular event happens. onreadystate is happens when the requests ready state changes.
In short onreadystate
Stores a function (or the reference of a function) to be called automatically each time the readyState property changes
Now for the line
xmlhttp.readyState==4 && xmlhttp.status==200
readyState : Holds the status of the XMLHttpRequest.
Changes from 0 to 4:
0: request not initialized
1: server connection established
2: request received
3: processing request
4: request finished and response is ready
And status Holds status
200: "OK"
404: Page not found
So xmlhttp.readyState==4 && xmlhttp.status==200 condition is true when the response is ready and there is no issues
xmlhttp.responseText contains the response sent from the server.
So document.getElementById("txtHint").innerHTML=xmlhttp.responseText; changes the HTML of the element with id txtHint to the response that was received.
Hope all the above made sense!!!
I'd like to address this comment: I've never been able to understand callbacks.
Consider this analogy:
You need want to rent that movie that just came out on VHS, so you
call Blockbuster and ask the attendant if they have a copy. Sadly
though, they are super busy dealing with thousands of David Bowie fans
who are trying to rent "Labyrinth" all at the same time and he does't
have time to look up the information for you. So instead, he asks for
your phone number. At some point in the future when the hordes of
people have left and he has the time, he looks up the info you need,
and calls you back on the number you provided. Turns out the movie is
sold out though, so he suggests "Dark Crystal" instead.
In your case you are dealing with an entity that is going to take a long time to do it's work as it needs to talk to remote servers, so it essentially asks you for your phone number so that when it's done you are called back as it were, with the requested data.
Does it make more sense now?
I searched stackoverflow but got contradictory answers:
Why should I reuse XmlHttpRequest objects?
Ajax-intensive page: reuse the same XMLHttpRequest object or create new one every time?
Also, there's a recommendation on w3schools.com :
If you have more than one AJAX task on your website, you should create
ONE standard function for creating the XMLHttpRequest object, and call
this for each AJAX task.
Why this recommendation? I'm instead using a global XMLHttpRequest object on my page for handling all Ajax tasks.
You misunderstood W3School's recommendation. I'll highlight the relevant part:
If you have more than one AJAX task on your website, you should create ONE standard function for creating the XMLHttpRequest object, and call this for each AJAX task.
It says that you use one AJAX function to fetch requests. This function will deal with the inconsistencies between IE and other browsers. XMLHttpRequest in standard-compliant browsers, and ActiveXObject in IE.
I recommend to use multiple XHR objects. With one global xhr object, your application can only deal with one request at a given time. It's also error-prone (eg. XMLHttpRequest launches multiple times without initiating the onreadystatechange function).
W3schools meant something like:
function createXHR() {
try {
return new XMLHttpRequest();
} catch (e) {
try {
return new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
return new ActiveXObject("Msxml2.XMLHTTP");
}
}
}
var xhr = createXHR();
xhr.open('get', '/test', true);
xhr.send();
Although it's better to create a function which handles requests, such as jQuery.ajax.
It is best to use different objects for each XHR you are making. Even if there's a way of doing it, avoid it! There's no problem with creating new object for each request. If you are worried about memory leak or something of that sort, do not worry, they are all properly GC`ed.
If you have more than one AJAX task on your website, you should create ONE standard function for creating the XMLHttpRequest object, and call this for each AJAX task.
It actually means that you have one function that creates a new object and returns it every time you call it. It something like:
function newXHR(){
return a new instance of XHR();
}
The recommendation you highlight is saying you should have one FUNCTION which handles AJAX, rather than specifically one XMLHTTPRequest object.
I would use a different one for each question.
The common argument against this concerns the overheads involved in setting up XHRs. However this is going to be pretty much negligible in any site that uses AJAX as it was intended (i.e. not as a labouring substitute for web sockets) and, in any case, much of the same overheads would apply with re-using an XHR. You'd still have to open the connection, fire it, attach listeners etc.
Browsers vary in terms of how many connection gateways are allowed at a given time, so it's up to the browser to control what XHRs can do what. In other words, you don't have to worry about managing this aspect.
Finally, there's nothing stopping you manually deleting the XHRs after you've used them, provided they are deletable (properties of an object rather than variables).
From MDN Web Docs:
If the httpRequest variable is used globally, competing functions
calling makeRequest() can overwrite each other, causing a race
condition. Declaring the httpRequest variable local to a closure
containing the AJAX functions avoids this.
Source: https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX/Getting_Started
I am using a pattern like this
var xhrSendBuffer = new Object();
function sendData(url, model) {
if (!xhrSendBuffer[url]) {
let xhr = new XMLHttpRequest();
xhr.onloadend = xhrDone;
xhr.error=xhrError;
xhr.onabort = xhrAbborted;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
xhrSendBuffer[url] = xhr;
}
xhrSendBuffer[url].send(JSON.stringify(model));
}
function xhrDone(e) {
console.log(e);
}
function xhrError(e) {
console.error(e);
}
function xhrAbborted(e) {
console.warn(e);
}
if I end up producing a DOS on my own site because I send to the same url multiple requests I could use the xhr.readyState to see how busy it is before sending the next request, however I have yet to encounter this as an issue.
In the follow ajax request could some one please explain (tryMS)
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;
}
Is (tryMS), and (otherMS) part of javascript or is it just a common argument used in the code, do they have specific functions? If its an argument wheres it value coming from.
In this case, tryMS and otherMS are just variable names. You could replace them with any valid variable name and the logic would be exactly the same. In this case, the object they will represent at runtime is a subclass of Exception as they are used in the catch clause of a try-catch statement.
You can read more about try-catch-finally here.
I wouldn't agree with the naming convention being used here, but the variable name is essentially describing the flow of control based on the browser being used. For example, if the creation of an XMLHttpRequest object causes an exception to be raised, then we should try an AJAX technique for microsoft browsers using ActiveXObject - hence the name tryMS.
Internet Explorer doesn't have an xhr XmlHttpRequest -- they have their own object for that. This code is trying to be browser agnostic; i.e. trying to work no matter the browser. The createRequest method tries to create an XMLHttpRequest. If that fails, it tries to create the first ActiveXObject. If that fails, it falls back to the next active x object.
Is (tryMS), and (otherMS) part of javascript or is it just a common
argument used in the code, do they have specific functions? If its an
argument wheres it value coming from.
try/catch statements pass the error to to the catch block. So tryMS and otherMS and failed are all just references to a string that describes the error.