I'm new in JS, and having quite hard time reading the following JS code.
The first parameter of the function is a url to a PHP script, the second is a string.
What confuses me is how to read code after the line:
self.xmlHttpReq.open('POST', strURL, true);
What happens after this? Which code should i look after this line? The script?
What happens after open?
function check_detail(strURL, pids)
{
var xmlHttpReq = false;
var self = this;
// Mozilla/Safari
if (window.XMLHttpRequest) {
self.xmlHttpReq = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject) {
self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
self.xmlHttpReq.open('POST', strURL, true);
self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
self.xmlHttpReq.onreadystatechange = function()
{
if (self.xmlHttpReq.readyState == 4)
updatepage(self.xmlHttpReq.responseText, pids);
}
self.xmlHttpReq.send(getquery(pids));
}
The key is the call to "send()", which actually launches the HTTP request. That happens, but the code then proceeds immediately without waiting for the result.
When the server responds, the browser will invoke the anonymous function set up as the "readystatechange" handler. Exactly when that happens is unpredictable; it's asynchronous, in other words.
Thus, the "updatepage()" call will happen long after the "check_detail()" function has returned.
When you make an Ajax request (which is what you are doing here) it is asynchronous, which means that you don't know exactly when it will return so you can't just wait for the return.
Instead, you set up your function so that, when the request returns, a function is kicked off to handle the response. This is the onreadystatechange piece.
So the chronology will be: first the send() will occur, which will send the result of the getquery() method up to the PHP page. When that returns, the function defined within onreadystatechange will fire, which will call updatepage() and pass it both the text that was sent back from the Ajax call, and also the pids parameter.
If you're new to JavaScript, then I'd say it's a waste of time trying to figure out what's going on here - you're learning how to use the XHR object, how to make that cross-browser, and you're learning JavaScript at the same time.
I'd recommend doing the Ajax with a JavaScript library such as jQuery - don't try to learn it all now while you're learning JavaScript as well.
Most of that could be replaced with something along the lines of:
$.post(strURL, function (data) {
updatePage(data);
});
this is simple Ajax function
function check_detail(strURL, pids)
{
// definning new variable
var xmlHttpReq = false;
// creating variable self which will function as this
var self = this;
// creating HTTP request maker for Mozilla/Safari
if (window.XMLHttpRequest) {
self.xmlHttpReq = new XMLHttpRequest();
}
// creating HTTP request maker in IE
else if (window.ActiveXObject) {
self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
// so this is the confusing part right ?
// xmlHttpReq.open opens connection tu the strURL and infomation sending method
// will be POST method ( other passible values can be GET method or even else )
self.xmlHttpReq.open('POST', strURL, true);
// this defines HTTP request header (small information about what we are sending)
// in fact this is sending Content-type of information
self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// when HTTP request maker state will be changed for example:
// the data will be sent or data will be received this function will be fired
self.xmlHttpReq.onreadystatechange = function()
{
// readyState 4 means data has been received
if (self.xmlHttpReq.readyState == 4)
updatepage(self.xmlHttpReq.responseText, pids); // updatepage is user defined function
}
// this actually sends the HTTP request which is made above
// but don't be confused because of this code ordering
// I mean the function defining what to do when content will be received is implemented
// before sending HTTP request right ?
// thats because if the data is too small and internet is really fast HTTP query can be
// executed faster then defining new function which will cause javascript error
self.xmlHttpReq.send(getquery(pids));
}
hope this helps
if not
more about ajax: http://en.wikipedia.org/wiki/Ajax_(programming)
Related
I think I ran into a problem of the same variable being used, I might have gotten lucky in some cases where they were separated by function scope. I recently replaced all of my jQuery code with plain JS and this broke a few things however the gained speed/lack of dependency(extra file to download) was good for me in this situation.
So I have the basic form of:
var http = new XMLHttpRequest(),
url = "php/my-script.php",
params = encodeURI('some-param='+value);
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function(data) {
//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
var result = JSON.parse(http.responseText);
if (result['status'] === "success") {
someFunction(result['some_key']);
}
}
}
http.send(params);
When I ran into the problem of the same http variable being used, I started to replace new ones with http1, http2, etc... seems like a bad idea. Especially having to replace all the http-method(?) calls afterwards like http2.responseText, etc... Should I make this into a function... then pass in the values to post and return the data out?
I guess I don't understand what happens when you call:
var http = new XMLHttpRequest();
Is that a one time use case, where after it has been called you need a new one for another post?
I will try the single-global-function approach. Everywhere I needed to do an AJAX call whether get or post, I always just used $.post/$.get on the spot, not sure if that's bad.
Let me explain the problem to you a little, I'm using a 3rd party plugin that runs a rest interface for executing database commands over a postgrest database. In order to limit the returned results so I don't call all 1,000 rows is to set the request header.
This is the plugins information on this:
Limiting
PostgREST uses HTTP range headers for limiting and describing the size of results. Every response contains the current range and total results:
Range-Unit: items
Content-Range → 0-14/15
This means items zero through fourteen are returned out of a total of fifteen -- i.e. all of them. This information is available in every response and can help you render pagination controls on the client. This is a RFC7233-compliant solution that keeps the response JSON cleaner.
To request limits and offsets translate into ranges and then set the request headers
Range-Unit: items
Range: 0-4
You can also use open-ended ranges for an offset with no limit: Range: 10-.
I'm writing my own java-script library to handle the rest calls for my project. thus, I'm trying to test limiting the results to just one row returned. However I get the following console error:
Uncaught InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.
Here is my code: note: I am going to add another var so when you make the call to get results you can set the limit programmable just trying to get it to work right now.
(function(window){
function defineCynergi(){
var Cynergi = {};
Cynergi.get = function(url){
var request = makeHttpObject();
request.open("GET", url, false);
request.setRequestHeader('Range-Unit', 'items');
request.setRequestHeader('Range', '0-1');
request.send(null);
return JSON.parse(request.responseText);
}
Cynergi.delete = function(url){
var request = new XMLHttpRequest();
request.open("DELETE", url, false);
request.setRequestHeader('Accept', 'application/:3000+json; version=1');
request.send();
deleteStatus = request.statusText;
return deleteStatus;
}
Cynergi.insert = function(url, data){
var request = new XMLHttpRequest();
request.open("POST", url, false);
request.setRequestHeader('Accept', 'application/:3000+json; version=1');
request.send(JSON.stringify(data));
sentStatus = request.statusText;
return sentStatus;
}
Cynergi.update = function(url, data){
var request = new XMLHttpRequest();
request.open("PATCH", url, false);
request.setRequestHeader('Accept', 'application/:3000+json; version=1');
request.send(JSON.stringify(data));
updateStatus = request.statusText;
return updateStatus;
}
return Cynergi;
}
if(typeof(Cynergi) === 'undefined'){
window.Cynergi = defineCynergi();
}
})(window);
function makeHttpObject() {
try {return new XMLHttpRequest();}
catch (error) {}
try {return new ActiveXObject("Msxml2.XMLHTTP");}
catch (error) {}
try {return new ActiveXObject("Microsoft.XMLHTTP");}
catch (error) {}
throw new Error("Could not create HTTP request object.");
}
and yes I know it would've been easier to use jquery, however for what i'm doing jquery doesn't work because of its precheck pass it sends to make sure the post is safe to go through isn't compatible with my plugin. This code is very early alpha stages but I've developed a pure js social media site in about 15 hours. I just get stuck on these little things because my lack of js knowledge. I also know that it would be better to set them up as asynchronous but I can't figure that out for the life of me although I've read count less post I can't seem to wrap my mind around it.
I have been using jquery libraries for implementing AJAX. it was ok and I am comfortable with that. However, I started reading some ajax book and found the following code.
// stores the reference to the XMLHttpRequest object
var xmlHttp = createXmlHttpRequestObject();
// retrieves the XMLHttpRequest object
function createXmlHttpRequestObject()
{
// will store the reference to the XMLHttpRequest object
var xmlHttp;
// if running Internet Explorer
if(window.ActiveXObject)
{
try
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e)
{
xmlHttp = false;
}
}// if running Mozilla or other browsers
else
{
try
{
xmlHttp = new XMLHttpRequest();
}
catch (e)
{
xmlHttp = false;
}
}
// return the created object or display an error message
if (!xmlHttp)
alert("Error creating the XMLHttpRequest object.");
else
return xmlHttp;
}
// make asynchronous HTTP request using the XMLHttpRequest object
function process()
{
// proceed only if the xmlHttp object isn't busy
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0)
{
// retrieve the name typed by the user on the form
name = encodeURIComponent(document.getElementById("myName").value);
// execute the quickstart.php page from the server
xmlHttp.open("GET", "quickstart.php?name=" + name, true);
// define the method to handle server responses
xmlHttp.onreadystatechange = handleServerResponse;
// make the server request
xmlHttp.send(null);
}
else
// if the connection is busy, try again after one second
setTimeout('process()', 1000);
}
//executed automatically when a message is received from the server
function handleServerResponse()
{
// move forward only if the transaction has completed
if (xmlHttp.readyState == 4)
{
// status of 200 indicates the transaction completed successfully
if (xmlHttp.status == 200)
{
// extract the XML retrieved from the server
xmlResponse = xmlHttp.responseXML;
// obtain the document element (the root element) of the XML structure
xmlDocumentElement = xmlResponse.documentElement;
// get the text message, which is in the first child of
// the the document element
helloMessage = xmlDocumentElement.firstChild.data;
// update the client display using the data received from the server
document.getElementById("divMessage").innerHTML =
'<i>' + helloMessage + '</i>';
// restart sequence
setTimeout('process()', 1000);
}
// a HTTP status different than 200 signals an error
else
{
alert("There was a problem accessing the server: " + xmlHttp.statusText);
}
}
}
Here my question is why do we use setTimeout('process()', 1000); in handleServerResponse() function? Can't we do this without setTimeout('process()', 1000);?
For me, it looks like some kind of constant polling. It's reusing the AJAX request over and over every second, and when the previous request is still active, it waits another second to send it again. So it's not just create an AJAX request and deal with the response.
Using that code, the page would be updating constantly with the information retrieved from the server. Whenever server response has changed, page will as well but not in real time (only when next request finishes). It's similar to Periodic Refresh.
As an evolution, you can have Long Polling in which you spawn an AJAX request and then wait until server responds. If any info is there in the server for you, you'll receive the response immediately. If, while you are waiting for response, anything comes to the server for you, you will receive it. If your request times out, server will respond with an empty body. Then, your client will spawn another AJAX request. You can get some more info from the Wikipedia. Extra link: Comet.
In the given example , the book has call the process() function on the body onload event.
When I change the code to onload-> to onkeyup <input type="text" id="myName" onkeyup="process()"/> I could remove the code //setTimeout('process()', 1000);
Is it possible to create a Javascript and include it in a web page that the function of this JS is to "catch" all GET request or any other Ajax calls made from any other Javascript on the page? Either to log it or just plain show it in a Alert box.
The "other Javacript" that will be executing GET or Ajax calls is arbitrary. I mean I have no control over that in terms of what it is.
And once caught I need to check which Javascript executing which GET or Ajax calls.
Is this possible?
Try this snippet. It extends the send function so that you can execute something before or after the real sending.
XMLHttpRequest.prototype.reallySend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
// Do something...
this.reallySend(body);
};
var req = new XMLHttpRequest();
req.open("GET", "any.html", true);
req.send(null);
const nativeOpen = XMLHttpRequest.prototype.open;
const proxiedOpen = function () {
if (arguments[1].includes('youUrl.com')) {
// do some ...
}
nativeOpen.apply(this, arguments);
};
Refer to the answer:
Intercept AND CHANGE the results of an ajax call
i am having trouble getting this XMLHttpRequest to work properly, this is my first time using ajax so i'm not sure if i'm formatting everything correctly. i have looked all over the web and i keep finding basically the same info and examples but certain elements are in different orders so i'm not sure which is correct and i've tried them all and nothing seems to work. here is my code:
function ajaxRequest(){
var activexmodes=["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"]
if (window.XMLHttpRequest)
return new XMLHttpRequest()
else if (window.ActiveXObject){
for (var i=0; i<activexmodes.length; i++){
try{
return new ActiveXObject(activexmodes[i])
}
catch(e){
//suppress error
}
}
}
else
return false
}
function getData(fileName){
var fileLoc =encodeURI("assets/"+fileName+".html")
alert(fileLoc)
var request = new ajaxRequest()
request.open("GET",fileLoc,true)
var response = request.responseText
alert(request.status)
alert(response)
request.send(null)
return response
}
function home() {
var data = getData("home")
var contentDiv = document.getElementByClassName(content)
contentDiv.innerHTML = data;
}
home is triggered when the user clicks on a div in the page. i know that getData is being accessed because the alerts pop up, however i get a status code of 0, this happened on both my local machine and on a live server. i read that localhosts can throw a 0 status regardless of the actual status but its happening on a live server as well. if someone could help me fix this issue and/or clarify the correct order of events in the function i would greatly appreciate it.
EDIT:
new code:
function getData(fileName){
fileLoc = encodeURI("assets/"+fileName+".html")
alert(fileLoc);
request.onreadystatechange = processData;
request.open("GET",fileLoc, false);
request.send();
alert(request.readyState);
alert(response);
}
function processData(){
if (request.readyState==4){
if (request.status==200){
document.getElementsByClassName('content').innerHTML = request.responseText;
}
else{
alert("An error has occured making the request");
}
}
}
You are telling XMLHTTPRequest to send the request asynchronous, which means the rest of your script gets executed while you wait for the response. You will get a reponse code 0 (uninitialized) and an empty response, because at the time you return from the function that is the current status and response.
Instead you want to define a function to call when the state changes, or let XMLHTTPRequest work synchronous.
Please refer to this tutorial for a simple example that should help you out.