Calling to ajax multiple times from javascript - javascript

for(var x=0 ; x<=23 ; x++)
{
AjaxRequest16 = null;
AjaxRequest16 = getXmlHttpRequestObject(); // method here to load the request
if(AjaxRequest16.readyState == 4 || AjaxRequest16.readyState == 0)
{
AjaxRequest16.open("GET", "ajax.php?id=16&AreaID=" +encodeURIComponent(AreaID)+ "&month="
+encodeURIComponent(document.getElementById("cboMonths").value)+ "&TimeSlot=" +encodeURIComponent(x), true);
AjaxRequest16.send(null);
AjaxRequest16.onreadystatechange = function()
{
if(AjaxRequest16.readyState == 4)
{
var innerHTML = AjaxRequest16.responseText.toString();
/* Retrieve data from the server and display. */
document.getElementById("divTime"+x).innerHTML = innerHTML;
}/* end if */
}/* end function */
}/* end if */
}/* end if */
I'm trying to call ajax multiple times to load data in a set of divs: 24 of them, they start with divTime0, divTime1, divTime2, divTime3...... divTime23. Each time its called, the value for the TimeSlot corresponds with the div e.g. TimeSlot=0 goes in divTime0.
I know the ajax calls here are overriding each other but have no idea how to solve it without writing out 24 blocks of code to get it working. N.B. this is working if i execute singularly without the for loop but it will just populate 1 of the 24 divs
The following code worked to load 24 divs with images:
for(var x=0 ; x<=23 ; x++)
document.getElementById("timeanalysisimg"+x).src="ajax.php?id=15&AreaID=" +encodeURIComponent(AreaID);
I'm trying to do something similar without having to write unnecessary code. Any ideas?
I got it working. Just pasting the solution
for(var x=0 ; x<=9 ; x++)
{
test(x, AreaID); // calling the function which resides externally to the loop
}
An external method:
function test(x, AreaID)
{
var AjaxRequest16 = null;
AjaxRequest16 = getXmlHttpRequestObject();
if(AjaxRequest16.readyState == 4 || AjaxRequest16.readyState == 0)
{
AjaxRequest16.open("GET", "ajax.php?id=16&AreaID=" +encodeURIComponent(AreaID)+ "&month="
+encodeURIComponent(document.getElementById("cboMonths").value)+ "&TimeSlot=" +encodeURIComponent(x), true);
AjaxRequest16.send(null);
AjaxRequest16.onreadystatechange = function()
{
if(AjaxRequest16.readyState == 4)
{
var innerHTML = AjaxRequest16.responseText.toString();
/* Retrieve data from the server and display. */
document.getElementById("divTime"+x).innerHTML = innerHTML;
}
}
}
}

Put the block into a function:
for(var x=0 ; x<=23 ; x++)
{
(function(x) {
var AjaxRequest16 = getXmlHttpRequestObject();
//rest of the code
}(x));
} //end of for loop

you can do something like:
for(var x=0 ; x<=23 ; x++)
{
req(x);
}
function req(x){
var AjaxRequest16 = null;
AjaxRequest16 = getXmlHttpRequestObject(); // method here to load the request
if(AjaxRequest16.readyState == 4 || AjaxRequest16.readyState == 0)
{
AjaxRequest16.open("GET", "ajax.php?id=16&AreaID=" +encodeURIComponent(AreaID)+ "&month="
+encodeURIComponent(document.getElementById("cboMonths").value)+ "&TimeSlot=" +encodeURIComponent(x), true);
AjaxRequest16.send(null);
AjaxRequest16.onreadystatechange = function()
{
if(AjaxRequest16.readyState == 4)
{
var innerHTML = AjaxRequest16.responseText.toString();
/* Retrieve data from the server and display. */
document.getElementById("divTime"+x).innerHTML = innerHTML;
}/* end if */
}/* end function */
}/* end if */
}

I changed all the code, but it does exactly what you want, without using asynchronous = false, and browser freezing:
function ajaxRequest(url, callback) {
var req = null;
if (window.XMLHttpRequest) req = new XMLHttpRequest();
else if (window.ActiveXObject) // if IE
{
try {
req = new ActiveXObject("Msxml2.XMLHTTP")
} catch (e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP")
} catch (e) {}
}
} else {
throw ("No Ajax support!");
return;
}
req.open('GET', url, true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
if (typeof (callback) == "function") callback(req);
}
};
req.send(null);
return req;
}
function loadMyData() {
var x = parseInt(arguments[0]);
if (x > 23) {
alert("all 24 is loaded!");
}
var url = "ajax.php?id=16&AreaID=" + encodeURIComponent(AreaID) +
"&month=" + encodeURIComponent(document.getElementById("cboMonths").value) +
"&TimeSlot=" + encodeURIComponent(x);
var callback = Function('req', 'document.getElementById("divTime' + x + '").innerHTML =' +
' req.responseText;' +
'loadMyData(' + x + ');');
ajaxRequest(url, callback);
}
loadMyData(0);

you should make your ajax calls asenkron false try this:
for(var x=0 ; x<=23 ; x++)
{
AjaxRequest16 = null;
AjaxRequest16 = getXmlHttpRequestObject(); // method here to load the request
if(AjaxRequest16.readyState == 4 || AjaxRequest16.readyState == 0)
{
AjaxRequest16.open("GET", "ajax.php?id=16&AreaID=" +encodeURIComponent(AreaID)+ "&month="
+encodeURIComponent(document.getElementById("cboMonths").value)+ "&TimeSlot=" +encodeURIComponent(x), false);
AjaxRequest16.send(null);
AjaxRequest16.onreadystatechange = function()
{
if(AjaxRequest16.readyState == 4)
{
var innerHTML = AjaxRequest16.responseText.toString();
/* Retrieve data from the server and display. */
document.getElementById("divTime"+x).innerHTML = innerHTML;
}/* end if */
}/* end function */
}/* end if */
}/* end if */

Sequentially load content with ajax
here is a simple ajax function for modern browsers (chrome,safari,ie10,android,ios)
function ajax(a,b,c){//url,function,just a placeholder
c=new XMLHttpRequest;
c.open('GET',a);
c.onload=b;
c.send()
}
and this is how you load content sequentially
var current=0,
x=23;
function handler(){
document.getElementById("divTime"+current).innerHTML=this.response;
current++
if(current<x){
ajax('url.php?id='+current,handler)
}
}
ajax('url.php?id='+current,handler);
this way you don't overwrite previous ajax calls.
Multiple simultaneous ajax calls is a bad solution.
anyway to achieve multiple ajax calls at the same time you need to create multiple ajax request functions.
var ajaxcall=[];
ajaxcall[0]=new XMLHttpRequest;
ajaxcall[0].CUSTOMID=0;
ajaxcall[0].open('GET','url.php?id='+0);
ajaxcall[0].onload=function(){console.log(this.CUSTOMID,this.response)};
ajaxcall[0].send();

What it boils down to is the asynchronous nature of Ajax calls.
Each Ajax context must be kept alive until the request is over (completion or failure).
In your initial code, you use only one Ajax request context. The loop launches the first request, but then overwrites its context immediately with the second one long before the first was processed. When the server responds (a few milliseconds later), there is no handler left on the browser side to process the response (except for the 24th one).
What your workaround does is to create a different context and callback for each request, since your global function stores them in different closures.
However, as a result you will fire a hail of 24 Ajax requests simultaneously on the server, which is likely to cause unnecessary overhead, or even crashes if your PHP script does not expect to execute concurrently on the same request. Besides, synchronizing your code on completion of these requests will not be easy.
Here is what I use for my own apps :
// --------------------------------------------------------------------
// Ajax lite
// --------------------------------------------------------------------
function PageCache (target, void_contents)
{
this.text = {};
this.req = {};
this.void_contents = void_contents || 'void';
this.target = target;
}
PageCache.prototype = {
// synchronous load
load: function (page)
{
if (!this.text[page]) this.text[page] = this._launch_request (page);
return this.text[page];
},
// asynchronous load
fetch: function (page, action)
{
if (this.text[page])
{
action (this, page);
return;
}
if (this.req[page]) return;
this.req[page] = this._launch_request (page,
function(_this, _page, _action) {
return function(){
_this._loader(_page,_action);
};
}(this,page,action));
},
_launch_request: function (page, callback)
{
var req;
try {
req = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
req.open('GET', this.target.replace (/\$/, page), callback!=undefined);
if (callback) req.onreadystatechange = callback;
req.send(null);
return callback ? req : this._get_result (req);
},
_get_result: function (req)
{
return (req.status < 400)
? req.responseText
: this.void_contents;
},
_loader: function (page, action)
{
if (!this.req[page] || (this.req[page].readyState != 4)) return;
this.text[page] = this._get_result (this.req[page])
delete this.req[page];
if (action) action (this.text[page], page);
}
}
In your example, you could use it like so:
First, a bit of cleanup :
function compute_id (AreaID,x) {
return "id=16&AreaID="
+ encodeURIComponent(AreaID)
+ "&month="
+ encodeURIComponent(document.getElementById("cboMonths").value)
+ "&TimeSlot="
+ x; // I suspect all the encodeURIComponent() calls are unnecessary
}
var Ajax = new PageCache (
'ajax.php?$', // '$' will be replaced with fetch() parameter
'error loading data'); // contents in case of request failure
1) simultaneous requests (not recommended)
for (var x = 0; x != 24 ; x++) {
// store current x value in a closure
var request_done = function (_x) {
return function (responseText) {
document.getElementById("divTime"+_x).innerHTML = responseText;
}}(x);
}
Ajax.fetch (compute_id (AreaID,x), request_done);
}
2) sequential blocking requests (very bad, don't do it unless your code cannot proceed without the data)
for (var x = 0; x != 24 ; x++) {
document.getElementById("divTime"+x).innerHTML =
Ajax.load (compute_id (AreaID,x));
}
3) sequential non-blocking requests
var AjaxCtx = { x:0, max:24};
// launch first request
Ajax.fetch (compute_id (AreaID, AjaxCtx.x), request_done);
function request_done (responseText) {
document.getElementById("divTime"+AjaxCtx.x).innerHTML = responseText;
// request completion triggers the next
if (++AjaxCtx.x != AjaxCtx.max)
Ajax.fetch (compute_id (AreaID,AjaxCtx.x), request_done);
}

Related

Add a delay between ajax get requests

I have a script that makes an ajax GET request once the user gets near the bottom of the page.
$(function(){
window.addEventListener('scroll', fetchImages);
window.addEventListener('scroll', fetchNotifications);
});
function fetchImages() {
var imagePage = $('.endless-pagination').data('next-page');
if(imagePage !== null) {
var last = $('.endless-pagination').data('last-item');
var within = $('.endless-pagination').data('within');
var orderBy = $('.endless-pagination').data('order-by');
clearTimeout( $.data( this, "scrollCheckImages" ) );
$.data( this, "scrollCheckImages", setTimeout(function() {
var scroll_position_for_images_load = $(window).height() + $(window).scrollTop() + 900;
if(scroll_position_for_images_load >= $(document).height()) {
$(".dual-ring-container").show();
$.ajax({
url: imagePage,
method: 'get',
cache: false,
})
.done(function( data ) {
if (last != null) {
$(".dual-ring-container").hide();
var newPageUrl = data.next_page + "&within=" + within + "&orderBy=" + orderBy + "&last=" + last;
$('.endless-pagination').append(data.images);
$('.endless-pagination').data('next-page', newPageUrl);
setResizeVariables();
updateReadMore();
initMentions();
}
});
}
}, 350))
}
}
However, there's a bit of a problem. This get request is essentially being spammed since the function is being triggered by a "scroll" event listener.
How could I make it so that this request can only be called once every few seconds or so?
Use a variable that keeps track of the last time the main body of the function was run, and return early if it was run less than a few seconds ago:
let lastCall = 0;
function fetchImages() {
const now = Date.now();
if (now - lastCall < 3000) return;
lastCall = now;
// ...
Note that you can use a similar strategy to reduce unnecessary indentation hell. Rather than
if (imagePage !== null) {
// big block of code
}
} // end of fetchImages
you can use
if (imagePage === null) return;
which will have the exact same effect, but will make your code a bit more readable.

Why is my function turning into a object?

I have several ajax requests in my project so to simplify my code i created a function to handle the requests.
I am passing a success function to load when status is == 200 however even though the data is being sent correctly i am receiving "uncaught type error success is not a function" error. Using typeof i can see success starts as a function but then displays as an object.
here is my code
//function to handle ajax requests
function sendRequest(link, requestType, success, data) {
var request = new XMLHttpRequest(),
url = link;
request.open(requestType, url, true);
request.onload = function () {
if (request.status >= 200 && request.status < 400) {
console.log("success");
var responseText = request.responseText;
console.log(typeof(success));
success(responseText);
} else {
consoloe.log("error");
}
}
request.send(data);
}
//calling function passing success function as argument
var jsonText = "json.php";
sendRequest(jsonText, 'GET', function (response) {
var json = JSON.parse(response),
postcodesArray = [],
jsonLength = json.length,
i;
for (i = 0; i < jsonLength; i++) {
postcodesArray.push(json[i].from_postcode);
}
var postcodes = postcodesArray.filter(Boolean),
pstcodeLength = postcodes.length,
n;
for (n = 0; n < pstcodeLength; n++) {
geocodeAddress(postcodes[n]);
}
});
//EDIT fiddle containing all my code
https://jsfiddle.net/x1qe73s8/
Reading your jsfiddle, your code is probably going through the sendLatLng function where you have
sendRequest(url, 'POST', null, data);
typeof null is "object".

passing variale to javascript callback function

Faced a problem with passing a variable into javascript callback function. Can't understand, why it doesn't work.
Here is the code. I pass variable 'i' through many functions. 'function1' is just an example, there is a big piece of code.
also the code in callback, 'var tmpl' is just an example, don't pay attention to that. The problem is why i can't pass 'i' variable.
function function1() {
for (var i = 0; i < 10; i++){
RequestData(i);
}
}
function RequestData(i, callback){
var xhr = new XMLHttpRequest();
xhr.open('GET', '/getitemID='+i, true);
xhr.send();
xhr.onreadystatechange = function() { // (3)
if (xhr.readyState != 4) return;
if (xhr.status != 200) {
alert(xhr.status + ': ' + xhr.statusText);
} else {
alert(xhr.responseText);
callback(JSON.parse(xhr.responseText));
}
xhr.close();
}
}
RequestData(i, function (json) {
alert('here!');
var tmpl = [
'<div id="content"><div id="bodyContent">',
'<button onclick="RequestData("+i+")">Load Data!</button></div>',
'<div>#here!</div>'
].join('');
var body = document.querySelector('body');
alert(body);
for (var i = 0; i < json.length; i++) {
var html = tmpl.replace('#here!', json[i].itemid);
body.insertAdjacentHTML('afterbegin', html);
}
});
if i try to calling callback like this: function RequestData(i, callback) {- i get 'unresolved type or variable 'i'' error, and callback doesn't work. else if i do not pass 'i' in callback - i do not get this error, but looks like callback doesn't work too, because this code for callback don't work RequestData(function (json) { alert('here!');} - i don't receive a message 'here', but no errors. in both situations callback call is: callback(JSON.parse(xhr.responseText));
First of all, i is undefined because you are calling RequestData(i, function()), while i is not defined.
You only call RequestData from function1() but that method is never executed and never has a callback specified.
To make it work, remove the RequestData(i) call from function1(). Then put the method call RequestData(i, function (json) { inside the the for loop. Finally call function1() and you will get your result. (not with clean code though).
function function1() {
for (var i = 0; i < 10; i++){
RequestData(i, function (json) {
alert('here!');
var tmpl = [
'<div id="content"><div id="bodyContent">',
'<button onclick="RequestData("+i+")">Load Data!</button></div>',
'<div>#here!</div>'
].join('');
var body = document.querySelector('body');
alert(body);
for (var i = 0; i < json.length; i++) {
var html = tmpl.replace('#here!', json[i].itemid);
body.insertAdjacentHTML('afterbegin', html);
}
});
}
}
function RequestData(i, callback){
var xhr = new XMLHttpRequest();
xhr.open('GET', '/getitemID='+i, true);
xhr.send();
xhr.onreadystatechange = function() { // (3)
if (xhr.readyState != 4) return;
if (xhr.status != 200) {
alert(xhr.status + ': ' + xhr.statusText);
} else {
alert(xhr.responseText);
callback(JSON.parse(xhr.responseText));
}
//xhr.close(); // this is not an existing function
}
}
// run the for loop by calling this method
function1();

jQuery ajax call not falling into success

I am new to doing jQuery ajax calls and am trying to test an ajax call I have attempted to write today. Here it is.
var heartbeatInterval = 30000;
var heartBeatTimer = null;
var retryCount = 0;
var maxRetries = 10;
$().ready(function () {
var url = $.url("/pollBulletin.htm");
heartBeatTimer = setInterval(function () {
$.ajax({
url: url,
type: 'GET',
error: function (data) {
retryCount = retryCount + 1;
if (heartBeatTimer != null && retryCount >= maxRetries) {
clearInterval(heartBeatTimer);
}
},
success: function (bulletinBarMessage) {
retryCount = 0;
var respContent = "";
respContent += bulletinBarMessage.messageLevel + " : ";
respContent += bulletinBarMessage.message;
}
});
// When communication with the server is lost stop the heartbeat.
}, heartbeatInterval);
});
At the moment the code is never falling into the success part of the call. Can someone confirm if it looks ok? I'm not sure if I have coded this right. I know the server side code is doing the write thing. At the moment it is just return a null (server side).
Server side...
public BulletinBarMessage getBulletinBarMessage() {
JdbcTemplate select = this.getJdbcTemplate();
List<BulletinBarMessage> messages = select.query(BULLETIN_LOOKUP_SQL, new BulletinBarMessageRowMapper());
BulletinBarMessage bulletinBarMessage = null;
if (messages != null && !messages.isEmpty()){
bulletinBarMessage = (BulletinBarMessage)messages.get(0);
}
return bulletinBarMessage;
}

Unexpected } tokens in js - trying to learn ajax

I'm just trying to learn some ajax so I wrote some code for basically an address book to pull some data. My javascript is rubbish but I cannot seem to understand what I am doing wrong, the error points to function ajaxCall but I see no issue with that function either:
(function () {
var searchForm = document.getElementById("search-form"),
searchField = document.getElementById("q"),
getAllButton = document.getElementById("get-all"),
target = document.getElementById("output");
var addr = {
search: function (event) {
var output = document.getElementById("output");
//start ajax call
ajaxCall("data/contacts.json", output, function (data) {
var searchValue = searchField.value,
addrBook = data.addressBook,
count = addrBook.length,
i;
//stop default behavior
event.preventDefault();
//clear target
target.innerHTML = "";
if (count > 0 && searchValue !== "") {
for (i = 0; i < count; i++) {
var obj = addrBook[i],
isItFound = obj.name.indexOf(searchValue);
if (isItFound !== -1) {
target.innerHTML += '<p>' + obj.name + ', ' + obj.email + '<p>';
} //end if isItFound
} //end for loop
} //end if count check
}); //end ajax call
}, //end method search
getAllContacts: function () {
var output = document.getElementById("output");
ajaxCall("data/contacts.json", output, function (data) {
var addrBook = data.addressBook,
count = addrBook.length,
i;
target.innerHTML = "";
if (count > 0) {
for (i = 0; i < count; i++) {
var obj = addrBook[i];
target.innerHTML += '<p>' + obj.name + ', ' + obj.email + '<p>';
} //end for loop
} //end if
}); //end ajax call
}, //end method getAllContacts
setActiveSection: function () {
this.parentNode.setAttribute("class", "active");
}, //end method setActiveSection
removeActiveSection: function () {
this.parentNode.removeAttribute("class");
}, //end method removeActiveSection
addHoverClass: function () {
searchForm.setAttribute("class", "hovering");
}, //end method addHoverClass
removeHoverClass: function () {
searchForm.removeAttribute("class");
} //end method removeHoverClass
} //end addr object
searchField.addEventListener("keyup", addr.search, false);
searchField.addEventListener("focus", addr.addActiveSection, false);
searchField.addEventListener("blur", addr.removeActiveSection, false);
getAllButton.addEventListener("click", addr.getAllContacts, false);
searchForm.addEventListener("submit", addr.search, false);
searchForm.addEventListener("mouseover", addr.addHoverClass, false);
searchForm.addEventListener("mouseout", addr.removeHoverClass, false);
})(); //end anon function
function getHTTPObject() {
var xhr;
//in most cases this first if is executed
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
//otherwise support crappy IE6 and below
else if (window.ActiveXObject) {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
return xhr;
}
function ajaxCall(dataUrl, outputElement, callback) {
//get ajax object
var request = getHTTPObject();
outputElement.innerHTML = "Loading...";
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
//good ajax response..now save it
var contacts = JSON.parse(request.responseText);
if (typeof callback === "function")
callback(contacts);
} //end upper if
} //end onreadystatechange
request.open("GET", dataUrl, true);
request.send(null);
}
The javascript development tools keeps giving me an unexpected token } on line 97 but that changes all so often. Am I missing a curly brace somewhere?
I did put your code to this fiddle and fixed the errors as far as i can.
You missed some curly braces and semicolons. Also, you used ajaxCall() and getHTTPObject() before they were declared. Check it out. Unfortunately, i dont know if the problem is already fixed, but now the code is valid at least :)
Btw: (in my opinion) such long Code-Samples are always better pasted into a fiddle. Not only because you can focus on the probably messy code here while referring to the complete code sample somewhere else, also because you can make sure that there are no syntax-errors as you can quickly validate you code using jsLint before asking the question here.
You must re-check what your JSON response is, in console, and see if it is invalid.
Because at that very 97 line you say that you are parsing a response.

Categories