properly queuing different ajax requests - javascript

I see a lot of solutions to queue ajax requests but I am trying to understand how to implement one for this case. Should it be a push and shift queue?:
var urlList = ['urlA', 'urlB', 'urlC', ...];
function initSession() {
for (var i = 0; i < urlList.length; i++) {
getResponse(urlList[i]); // this is what I would like to queue.
}
}
function getResponse(theURL) {
steps.shuffleLetters({
"text": messages[mesInd]
});
$.ajax({
method: 'GET',
url: theURL,
dataType: 'text',
success: function(data) {
setTimeout(function() {
steps.shuffleLetters({
"text": data
});
}, 1000);
mesInd = mesInd + 1;
},
error: function(data) {
setTimeout(function() {
steps.shuffleLetters({
"text": "Click Again!"
});
}, 1000);
mesInd = 0;
}
});
}

You can do that by removing the for loop and call the next url after the success of the current request
Check the code below:
var urlList = ['urlA','urlB','urlC',...];
var length = urlList.length;
var currentRequest = 0;
getResponse(urlList[currentRequest]);
function getResponse(theURL){
steps.shuffleLetters({"text": messages[mesInd]});
$.ajax({
method: 'GET',
url: theURL,
dataType: 'text',
success: function (data) {
setTimeout(function(){steps.shuffleLetters({"text": data});}, 1000);
//Here you will call the next request
currentRequest +=1;
if(currentRequest < length)
{
getResponse(urlList[currentRequest]);
}
mesInd = mesInd+1;
},
error: function (data) {
setTimeout(function(){steps.shuffleLetters({"text": "Click Again!"});}, 1000);
mesInd = 0;
}
});
}

Related

how to speed up ajax calls to fetch record from php file

i'm trying to send ajax call to php file which return 1000 record at a time in json encoded format which i am appending in table. everything working fine but it takes alot for time which result in hanging of page. below is my js code.
$(window).load(function() {
for (i = 0; i < 31; i++)
{
$.ajax({
type: "GET",
url: "filters.php",
data: {limit: 1000, start_from: (i * 1000)},
success: function(response) {
var array = JSON.parse(response);
Object.keys(array).forEach(function(key) {
oTable.fnAddData([
array[key][1],
array[key][2],
array[key][3],
array[key][4],
array[key][5],
array[key][6],
array[key][7],
array[key][8],
array[key][9],
array[key][10],
array[key][11],
array[key][12],
array[key][13],
array[key][14],
array[key]['link']
]);
});
},
datatype: 'json'
});
}
});
Try this:
$(window).load(function() {
for (i = 0; i < 31; i++)
{
setTimeout(500,function(){
$.ajax({
type: "GET",
url: "filters.php",
data: {limit: 1000, start_from: (i * 1000)},
success: function(response) {
var array = JSON.parse(response);
Object.keys(array).forEach(function(key) {
oTable.fnAddData([
array[key][1],
array[key][2],
array[key][3],
array[key][4],
array[key][5],
array[key][6],
array[key][7],
array[key][8],
array[key][9],
array[key][10],
array[key][11],
array[key][12],
array[key][13],
array[key][14],
array[key]['link']
]);
});
},
datatype: 'json'
});
});
}
});

Second Jquery json getting fired before first Jquery being complete

I have two javascript function which populate some data using jquery json. Both working fine but problem is that second function getting called before first one execute. My code is :
$(document).ready(function () {
loadSubject();
getTopic();
});
function loadSubject() {
var CourseId = document.getElementById('CourseId').value;
alert('22222');
jQuery.support.cors = true;
$.ajax({
url: 'http://220.45.89.129/api/LibraryApi',
type: 'Get',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: { DataType: 'Subject', UserRecId: 0, ParentId: CourseId },
dataType: 'json',
success: function (data) {
var subjectDivs = "";
var divs = "";
var i = 1;
$.each(data, function (index, value) {
divs = "";
// Some code here
i = i + 1;
});
subjectDivs = subjectDivs + divs;
alert('11111');
$('#cCount').val(i);
document.getElementById('accordion').innerHTML = subjectDivs;
},
error: function (e) {
alert(JSON.stringify(e));
}
});
}
function getTopic() {
var c = $('#cCount').val();
alert(c);
for (var i = 1; i <= c; i++) {
var subId = $('#hdn_' + i).val();
jQuery.support.cors = true;
$.ajax({
url: 'http://220.45.89.129/api/LibraryApi',
type: 'Get',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: { DataType: 'Topic', UserRecId: 0, ParentId: subId },
dataType: 'json',
success: function (data) {
var topicDivs = "";
var divs = "";
tDivs = '';
$.each(data, function (index, value) {
divs = '';
divs = '<div class="row">';
divs = divs + '<div class="subject">' + value.Name + '</div>';
divs = divs + "</div>";
topicDivs = topicDivs + divs;
});
$('#sDiv_' + i).html(topicDivs);
},
error: function (e) {
alert(JSON.stringify(e));
}
});
}
}
This is not the way how ajax get executes. If you put two jquery ajax requests one by one then they will execute in sequence by it is not necessary that second request will be executed after first request completes or response of first request is received.
If you want this to happen then there are two ways
1. Use async:'false'
This makes a request to wait until response is recieved before executing next statement in javascript.
What does "async: false" do in jQuery.ajax()?
2. Use callbacks
Write the second function which you want to execute in success or complete callback of your first ajax request.
jQuery ajax success callback function definition
Try adding return statement before $.ajax({}) within both loadSubject and getTopic , to return jQuery promise object , which can be handled at deferred.then
function loadSubject() {
return $.ajax()
}
function getTopic() {
return $.ajax()
}
loadSubject().then(getTopic);
function a() {
return new $.Deferred(function(dfd) {
setTimeout(function() {
dfd.resolve(1)
}, 2000)
}).promise().then(function(data) {
console.log(data)
})
}
function b() {
return new $.Deferred(function(dfd) {
setTimeout(function() {
dfd.resolve(2)
}, 2000)
}).promise().then(function(data) {
console.log(data)
})
}
a().then(b)
You have to add async:false in your first ajax request, it stop next execution till first ajax request will complete its execution.
So your first function like this
function loadSubject() {
var CourseId = document.getElementById('CourseId').value;
jQuery.support.cors = true;
$.ajax({
url: 'http://220.45.89.129/api/LibraryApi',
type: 'Get',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: { DataType: 'Subject', UserRecId: 0, ParentId: CourseId },
dataType: 'json',
async:false,
success: function (data) {
var subjectDivs = "";
var divs = "";
var i = 1;
$.each(data, function (index, value) {
divs = "";
// Some code here
i = i + 1;
});
subjectDivs = subjectDivs + divs;
alert('11111');
$('#cCount').val(i);
document.getElementById('accordion').innerHTML = subjectDivs;
},
error: function (e) {
alert(JSON.stringify(e));
}
});
}
Call second function from first ajax success function
$(document).ready(function () {
loadSubject();
});
function loadSubject() {
// code here
$.ajax({
url: 'http://220.45.89.129/api/LibraryApi',
type: 'Get',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: { DataType: 'Subject', UserRecId: 0, ParentId: CourseId },
dataType: 'json',
success: function (data) {
//code here
getTopic(); // Second function calling
},
error: function (e) {
alert(JSON.stringify(e));
}
});
}
Now when first function is executed successfully then second function will be called.

How show loading window in async query?(or may be sync)

i have:
function load_data(data) {
var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
myMask.show();
$.ajax({
url: '/dostup/data_json.php',
method: 'GET',
async: true,
data: {
epsg: data
},
dataType: 'json',
error: function(jqXHR, status, error) {
console.log('ошибка получения данных: '+data);
},
success: function(data2) {
window[data] = data2;
window[data+"_layer"].clearLayers();
window[data+"_layer"].addData(eval(data));
myMask.hide();
}
});
}
And myMask hidden before window[data] loading on site(client).
I try set async: false and myMask not show(i try and beforeSend too).
P.S. i have:
function search_handler(val) {
search_list=[];
for (var t = 0; t < layer_array.length; t++) { //>
if (window[layer_array[t]] != undefined && !eval(layer_array[t]).features) load_data(layer_array[t]);
if (window[layer_array[t]] != undefined && eval(layer_array[t]).features) {
for (var i = 0; i < eval(layer_array[t]).features.length; i++) { //>
search_list.push(eval(layer_array[t]).features[i]);
}
}
}
....more script
}
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You need to use ajaxStart and ajaxStop like that:
$(document)
.ajaxStart(function () {
myMask.show();
})
.ajaxStop(function () {
myMask.hide();
});

Multiple ajax calls when previous one completes

I have these ajax calls that need to get called when the previous one is success, meaning once the first ajax is OK, call the 2nd ajax, once the 2nd ajax is OK call the 3rd one, etc so on. I started with a few ajax calls so it was fine to chain them up like this below but now I have about 20 of them and it'd be a mess to chain them up like this.
$.ajax({
url: 'urlThatWorks1',
success: function (data) {
//call someMethod1 with data;
$.ajax({
url: 'urlThatWorks2',
success: function (data) {
//call method2 with data;
//another ajax call ... so on
}
}.... 19 level deep
So I need to make it bit easier to read and maintain so I'm thinking something like
var ajaxArray = [];
var function1 = $.ajax('urlThatWorks1', data I get back from the 'urlThatWorks1' call);
myArray.push(function1);
var function2 = $.ajax('urlThatWorks2', data I get back from the 'urlThatWorks2' call);
myArray.push(function2);
//etc 19 others
myArray.each(index, func){
//Something like $.when(myArray[index].call()).done(... now what?
}
Hope this makes sense, I'm looking for a way of ajax call array from which I can call an ajax call on whose success I call the next ajax in the array. Thanks.
Create a recursive function to be called in sequence as the ajax requests return data.
var urls = [ "url.1", "url.2", ... ];
var funcs = [];
function BeginAjaxCalls()
{
RecursiveAjaxCall(0, {});
}
function RecursiveAjaxCall(url_index)
{
if (url_index >= urls.length)
return;
$.ajax(
{
url: urls[url_index],
success: function(data)
{
funcs[url_index](data);
// or funcs[urls[url_index]](data);
RecursiveAjaxCall(url_index + 1);
}
});
}
funcs[0] = function(data)
// or funcs["url.1"] = function(data)
{
// Do something with data
}
funcs[1] = function(data)
// or funcs["url.2"] = function(data)
{
// Do something else with data
}
Try
$(function () {
// requests settings , `url` , `data` (if any)
var _requests = [{
"url": "/echo/json/",
"data": JSON.stringify([1])
}, {
"url": "/echo/json/",
"data": JSON.stringify([2])
}, {
"url": "/echo/json/",
"data": JSON.stringify([3])
}];
// collect responses
var responses = [];
// requests object ,
// `deferred` object , `queue` object
var requests = new $.Deferred() || $(requests);
// do stuff when all requests "done" , completed
requests.done(function (data) {
console.log(data);
alert(data.length + " requests completed");
$.each(data, function (k, v) {
$("#results").append(v + "\n")
})
});
// make request
var request = function (url, data) {
return $.post(url, {
json: data
}, "json")
};
// handle responses
var response = function (data, textStatus, jqxhr) {
// if request `textStatus` === `success` ,
// do stuff
if (textStatus === "success") {
// do stuff
// at each completed request , response
console.log(data, textStatus);
responses.push([textStatus, data, $.now()]);
// if more requests in queue , dequeue requests
if ($.queue(requests, "ajax").length) {
$.dequeue(requests, "ajax")
} else {
// if no requests in queue , resolve responses array
requests.resolve(responses)
}
};
};
// create queue of request functions
$.each(_requests, function (k, v) {
$.queue(requests, "ajax", function () {
return request(v.url, v.data)
.then(response /* , error */ )
})
})
$.dequeue(requests, "ajax")
});
jsfiddle http://jsfiddle.net/guest271314/6knraLyn/
See jQuery.queue() , jQuery.dequeue()
How about using the Deferred approach. Something like:
var arrayOfAjaxCalls = [ { url: 'https://api.github.com/', success: function() { $("#results").append("<p>1 done</p>"); } },
{ url: 'https://api.github.com/', success: function() { $("#results").append("<p>2 done</p>"); } },
{ url: 'https://api.github.com/', success: function() { $("#results").append("<p>3 done</p>"); } },
{ url: 'https://api.github.com/', success: function() { $("#results").append("<p>4 done</p>"); } },
{ url: 'https://api.github.com/', success: function() { $("#results").append("<p>5 done</p>"); } },
{ url: 'https://api.github.com/', success: function() { $("#results").append("<p>6 done</p>"); } },
{ url: 'https://api.github.com/', success: function() { $("#results").append("<p>7 done</p>"); } },
{ url: 'https://api.github.com/', success: function() { $("#results").append("<p>8 done</p>"); } },
{ url: 'https://api.github.com/', success: function() { $("#results").append("<p>9 done</p>"); } }
];
loopThrough = $.Deferred().resolve();
$.each(arrayOfAjaxCalls, function(i, ajaxParameters) {
loopThrough = loopThrough.then(function() {
return $.ajax(ajaxParameters);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="results"></div>
You could use the async library, which has a bunch of functions like waterfall or series which could solve your problem.
https://github.com/caolan/async#series
https://github.com/caolan/async#waterfall

jQuery ajax loop and iteration scope

I'm wondering why in the code below the i variable still shows "5" instead of showing "1" then "2" then "3" and so on ? Must be a scope issue but I don't really get it as I changed the scope of i variable in global and dom scope and still getting the same problem.
When I alert i outside the ajax function, it works well.
for (var i = 0; i < 5; i++) {
$.ajax({
url: '/echo/html/',
method:'post',
data: {
html: 'Ajax data'
},
success: function (resp) {
$('#success').append(i) // always 5
}
})
$('#outsideAjax').append(i); // is okay
}
Here is the fiddle
EDIT :
I went for #Tushar Gupta solution as it best suits my needs but I get another issue, the iteration won't work if I set this option : processData: false
See the fiddle
Why is this not working ?
This is due to Closures in JavaScript. Here's the fix -
for (var i = 0; i < 5; i++) {
(function(i){
$.ajax({
url: '/echo/html/',
method:'post',
data: {
html: 'Ajax data'
},
success: function (resp) {
$('#success').append(i)
}
})
})(i);
$('#outsideAjax').append(i);
}
you can fix this using closures, wrapping the value of i:
for (var i = 0; i < 5; i++) {
(function(val){
$.ajax({
url: '/echo/html/',
method:'post',
data: {
html: 'Ajax data'
},
success: function (resp) {
$('#success').append(val);
}
})
$('#outsideAjax').append(val); // is okay
})(i);
}
fiddle Demo
var i = 0;
function ajax_call() {
$.ajax({
url: '/echo/html/',
method: 'post',
data: {
html: 'Ajax data'
},
success: function (resp) {
$('#success').append(i++);
if (i < 5) {
ajax_call();
}
}
});
$('#outsideAjax').append(i);
};
ajax_call();
Solution using Function#bind():
http://jsfiddle.net/RQncd/1/
for (var i = 0; i < 5; i++) {
$.ajax({
url: '/echo/html/',
method:'post',
data: {
html: 'Ajax data'
},
success: (function (i, resp) {
$('#success').append(i);
}).bind(null, i)
});
$('#outsideAjax').append(i);
}

Categories