execute code after AJAX loop finished - javascript

I have an AJAX call that gets called "i" amount of times. I want to execute the rest of the code only after the last AJAX processData callback function was finished (It fills values of the .csv into an array called "lines" and I need the finished array after all iterations have finished). So far it only works by using "setTimeout()" which is not a nice solution
for (var i = 0; i < options.length; i++) {
(function(index) {
$.ajax({
type: "GET",
url: options[index] + ".csv",
dataType: "text",
success: function(data) {
processData(data, options[index], type)
}
});
})(i);
}
setTimeout(function() {
getAveragePercentages(lines);
}, 500)

You can use the JavaScript promise functionality.
Make AJAX request in the promise.
Create an array which will contains all these promise.
Promise.all will be executed after all promise get resolved.
var promiseArr = [];
for (var i = 0; i < options.length; i++) {
var promise = new Promise(function(resolve, reject) {
(function(index) {
$.ajax({
type: "GET",
url: options[index] + ".csv",
dataType: "text",
success: function(data) {
processData(data, options[index], type); resolve('outputIfany')
}
});
})(i);
});
promiseArr.push(promise);
}
Promise.all(promiseArr).then(function(values) {
getAveragePercentages(lines);
});

for (var i = 0; i < options.length; i++) {
(function (index) {
$.ajax({
type: "GET",
url: options[index] + ".csv",
dataType: "text",
success: function (data) {
processData(data, options[index], type)
}
});
counter = counter + 1;
})(i);
if (i == options.length) {
getAveragePercentages(lines);
}
}

You can do something like this.
after last Loop Success call function
var totalRec = options.length;
for(var i=0;i<options.length;i++){
(function(index){
$.ajax({
type: "GET",
url: options[index]+".csv",
dataType: "text",
success: function(data) {processData(data, options[index], type)
if(i == (totalRec-1)){
getAveragePercentages(lines);
}
}
});
})(i);
}
or
var totalRec = options.length;
for(var i=0;i<options.length;i++){
(function(index){
$.ajax({
type: "GET",
url: options[index]+".csv",
dataType: "text",
success: function(data) {processData(data, options[index], type)
}
});
})(i);
if(i == (totalRec-1)){
getAveragePercentages(lines); // gets called only when condition is true
}
}

It is not a good practice to use a setTimeOut for wait the ajax call, in my experience I've been using recursive functions for doing this, in your case you can do the following:
var counter = 0;
function main()
{
counter = 0;
doAjaxCall(counter);
}
function doAjaxCall(counter)
{
(function(index){
$.ajax({
type: "GET",
url: options[index]+".csv",
dataType: "text",
success: function(data) {
processData(data, options[index], type);
if(counter < options.length)
{
counter++;
doAjaxCall(counter); //We call the same function but with the next index
}
else
{
//The loop finished, countinue code after your for loop
}
}
});
})(i);
}

set up a counter and check it's value before calling your function
$("#counter").html("0");
for(var i=0;i<options.length;i++){
(function(index){
$.ajax({
type: "GET",
url: options[index]+".csv",
dataType: "text",
success: function(data) {
processData(data, options[index], type)
var counter = $("#counter").html();
if( counter == options.length ){
getAveragePercentages(lines);
}
$("#counter").html(counter+1);
}
});
})(i);
}

I added a function as a parameter. The AJAX calls the function when the load is completed.
function loadDoc(call_back_func) {
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
json_data = JSON.parse(this.responseText);
call_back_func();
}
xhttp.open("GET", "kanban_personal_template.json");
xhttp.send();
}
function load_call_back()
{
console.log(json_data);
}
loadDoc(load_call_back);

Related

Get property to array and write it to new array (JS)

I have code to get data from google api.
Here is the code:
$.ajax({
url: dburl,
dataType: 'json',
async: false,
type: 'GET',
data: model,
success: function (data) {
if (data.length !== 0) {
speeddata = data;
for (var i = 0; i < speeddata.length; i++) {
path = "path=" + speeddata[i].Latitude2 + ',' + speeddata[i].Longitude2;
var googleurl = "https://roads.googleapis.com/v1/speedLimits?"
+ path + "&key=" + roadsapikey;
$.ajax({
url: googleurl,
dataType: 'json',
async: false,
type: 'GET',
success: function(data) {
speedlimits = data;
console.log(speedlimits);
for (var i = 0; i < speedlimits.length; i++) {
speedobject.push({
speedlimits: speedlimits[i].speedLimits.speedLimit
});
}
console.log(speedobject);
}
});
}
}
},
error: function () {
alert("Error");
}
});
Here is what I get in response here - speedlimits
Response
I try to take speedLimit property and push it to new object.
Like this:
for (var i = 0; i < speedlimits.length; i++) {
speedobject.push({
speedlimits: speedlimits[i].speedLimits.speedLimit
});
}
But when I show speedobject in console it is empty.
Why so? Where is my problem?
The speedlimits object looks like this:
speedlimits = { // You're looping over this (speedlimits)
speedLimits: [ // You should be looping over this (speedlimits.speedLimits[i])
{speedLimit: 50},
// ...
],
snappedPoints: []
}
You are trying to loop over the speedLimits and snappedPoints items - not the elements within speedLimits.
for (var i = 0; i < speedlimits.speedLimits.length; i++) {
speedobject.push({
speedlimits: speedlimits.speedLimits[i].speedLimit
});
}
according to the data example here the api returns an object, not an array.. so your success function would look like this.. Make sure you get the case right too.
success: function(data) {
speedlimits = data.speedLimits;
console.log(speedlimits);
for (var i = 0; i < speedlimits.length; i++) {
speedobject.push({
speedlimits: speedlimits[i].speedLimit
});
}
console.log(speedobject);
}

Break the for loop based on the ajax success variable

For the following code, the emailCnt is 50 for first iteration, I need 25 in next iteration. What is the possible way to access the variable value outside the ajax success and break the for loop execution?
var limit = 50;
var emailCnt = limit;
for (var i = 0; i < 20; i++) {
console.log(emailCnt);///this value is 50 instead I need 25
if (emailCnt < limit && i != 0) {
break;
}
setTimeout(function () {
submit_post(slNo, limit, function (output) {
slNo = output;
emailCnt = 25;
$('#load_data').html('Hello');
});
}, 1000);
}
function submit_post(slNo, limit, handleData) {
$.ajax({
type: 'POST',
async: false,
url: url,
data: { slNo: slNo, limit: limit },
success: function (data) { handleData(data); }
});
}
This successfully worked for me
var limit = 50;
var emailCnt = limit;
function submit_post(slNo, limit)
{
var result="";
$.ajax({
type: 'POST',
async: false,
url: url,
data: {slNo:slNo, limit:limit},
success: function(data) { result = data; }
});
return result;
}
for(var i=0;i<20;i++)
{
if(emailCnt < limit && i != 0)
{
break;
}
setTimeout(function () {
var output = submit_post(slNo, limit);
slNo = output;
emailCnt = 25;
$('#load_data').html('Hello');
}, 1000);
}

How to return a parent function when the function is recursive Javascript

I've been completing FreeCodeCamp and have given myself the task of fetching an image from the Wikipedia API. I am so close but I am just having trouble with this recursive function.
I'm having some trouble with an ajax request. I want the whole success function to return when obj===label. However, it is only returning one instance of findObjByLabel().
What can I do to make the success function completely return as soon as the label is found?
var wikiUrl = "https://en.wikipedia.org/w/api.php?action=query&format=json&titles=India&prop=pageimages&pithumbsize=300&callback=?";
// this retrieves info about the wikiUrlImg
$.ajax( {
url: wikiUrl,
data: {
format: 'json'
},
dataType: 'json',
type: 'GET',
headers: { 'Api-User-Agent': 'Example/1.0' },
success: function(data) {
console.log("wiki api success");
var findLabel = findObjByLabel(data,"India",1);
function findObjByLabel(obj, label, iterrations){
var itterationLimit = "9";
if (iterrations < itterationLimit){
for(var i in obj){
if(obj === label){
console.log(">>>>>>>>>>>>>>>>>>>>>>> !!!its the label!!! <<<<<<<<<<<<<<<<<<<<<<<<");
// ****************I want the success function to return here! ****************
return "something";
}else{
console.log(">>>>>>>>>>>>>>>>>>>>>>>its not the label<<<<<<<<<<<<<<<<<<<<<<<<");
console.log("i= " + i);
if(obj.hasOwnProperty(i)){
iterrations+=1;
console.log("obj[i] : " + obj[i]);
var foundLabel = findObjByLabel(obj[i], label, iterrations);
}
}
}
}
}//end of findObjByLabel function
}, //end of success
error: function(){
console.log("failure of getWiki api");
}
});
Substitute obj[i] for obj at if condition, use break within if statement, place return statement outside of for loop
var wikiUrl = "https://en.wikipedia.org/w/api.php?action=query&format=json&titles=India&prop=pageimages&pithumbsize=300&callback=?";
// this retrieves info about the wikiUrlImg
$.ajax({
url: wikiUrl,
data: {
format: 'json'
},
dataType: 'json',
type: 'GET',
headers: {
'Api-User-Agent': 'Example/1.0'
},
success: function(data) {
console.log("wiki api success");
var findLabel = findObjByLabel(data, "India", 1);
function findObjByLabel(obj, label, iterrations) {
var itterationLimit = "9";
if (iterrations < itterationLimit) {
for (var i in obj) {
if (obj[i] === label) {
console.log(">>>>>>>>>>>>>>>>>>>>>>> !!!its the label!!! <<<<<<<<<<<<<<<<<<<<<<<<");
// ****************I want the success function to return here! ****************
break; // break `for` loop
} else {
console.log(">>>>>>>>>>>>>>>>>>>>>>>its not the label<<<<<<<<<<<<<<<<<<<<<<<<");
console.log("i= " + i);
if (obj.hasOwnProperty(i)) {
iterrations += 1;
console.log("obj[i] : " + obj[i]);
var foundLabel = findObjByLabel(obj[i], label, iterrations);
}
}
}
}
return "something"; // return `"something"`
} //end of findObjByLabel function
console.log(findLabel); // "something"
}, //end of success
error: function() {
console.log("failure of getWiki api");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Update textarea after get response from servlet in javascript

I have a program which calls a function in javascript with 1 o more requests to 1 servlet, I want to execute request after request and get the response after each exucution, to make this I have 1 function, but it only shows the result after all requests have been executed.
function cmd(args) {
width = 0;
var res = args.split('\n');
var largo = res.length;
var progressLength = 100 / largo;
for (var i = 0; i < largo; i++)
{
if (res[i] == 'desconectar')
{
desconectar();
break;
}
else
{
executeCMD(res[i]);
}
}
}
function executeCMD(args)
{
$.ajax({
type: "POST",
url: 'Controlador',
data: {cmd: args, operacion: 1},
success: function (response) {
document.getElementById('respuesta').value = document.getElementById('respuesta').value + response;
},
dataType: 'text',
async: false
});
}
If I add window.alert(response); inside success field it shows the progress step by step and works fine, but it show alerts which I don't want.
This is I want http://imgur.com/a/9nclR but I'm getting only last picture.
The solution if anyone is intersting was using a recursive function as next:
function cmd(args) {
width = 0;
move(0);
var res = args.split('\n');
var largo = res.length;
var valInit = 0;
if (largo > valInit)
{
executeCMD(res, valInit);
}
}
function executeCMD(args, i)
{
$(document).ready(function () {
$.ajax({
type: "POST",
url: 'ControladorServlet',
data: {cmd: args[i], operacion: 1, ticket: ticket, iddispositivo: sesion},
success: function (response) {
var textarea = document.getElementById('respuesta');
var res = response.trim().split('\n');
if(error){//dc}
else
{
document.getElementById('respuesta').value = document.getElementById('respuesta').value + response.trim() + "\n\n";
var valor = (100) * (i + 1) / args.length;
move(valor);
if (i + 1 < args.length)
{
executeCMD(args, i + 1);
}
}
},
dataType: 'text'
});
});
}

method is executing before ajax call getting completed

I am trying to call a method after all ajax calls gets completed but some reason the method id getting triggered before one of the ajax call is getting completed. i tried to keep the method in ajax complete section and using $.when() and async:false but i am getting same result. I don't know if its because i am using jsonp ?
My jquery version is 1.11.0
Below is my code
function getBBTrending() {
bbProductD = [];
jQuery.ajax({
type: "GET",
url: "crazycalls/getbbtrending.php",
// cache must be true
cache: true,
crossDomain: true,
success: function (data) {
bbTrending = data.results;
for (var i = 0; i < 4; i++) {
getProductdetails(bbTrending[i].productLink);
}
},
dataType: 'json'
});
}
function getProductdetails(pLink) {
jQuery.ajax({
type: "GET",
url: pLink,
// cache must be true
cache: true,
crossDomain: true,
success: function (data) {
pushArray(bbProductD, data);
},
dataType: 'jsonp'
});
}
function pushArray(array1,data1)
{
array1.push(data1);
}
// this function is executing before pushArray(array1,data1)
jQuery( document ).ajaxStop(function() {
displayProducts(bbProductD);
})
function displayProducts(bbProductD)
{
jQuery("#bbButtongroup").show();
var rProducts = bbProductD;
var rating;
var html = ['<div class="row">']
for (var i = 0; i < rProducts.length; i++)
{
var entry = rProducts[i];
var title = entry.name
var Tnail = entry.image;
var sPrice = entry.salePrice;
var rPrice = entry.regularPrice;
var hcode = '<div class="col-sm-6 col-md-4"><div class="thumbnail"><img style="height: 200px; width: 100%; display: block;" src=\" '+ Tnail + '\" alt="..."><div class="caption"><h3 style="font-size: 14px;">'+ title +'</h3><p><span class="label label-info"> Regular Price : '+ rPrice +'</span></p><p><span style="float: right;" class="label label-info">Sale Price :'+ sPrice +'</span></p><p>BuyView</p></div></div></div>';
html.push(hcode);
}
html.push('</div>');
document.getElementById('pContainer').innerHTML = html.join('');
}
this is how i added using $.when
jQuery.when( { getBBTrending(),getProductdetails()}).done(function() {
displayProducts(bbProductD);
});
any advice?
The asynchronous way, using async library
function getBBTrending() {
bbProductD = [];
jQuery.ajax({
//stuff...
success: function (data) {
bbTrending = data.results;
async.each(bbTrending, function(element, callback){
getProductdetails(element.productLink, callback);
}, function(err){
displayProducts(bbProductD);
});
},
});
}
function getProductdetails(pLink, callback) {
jQuery.ajax({
//stuff
success: function (data) {
pushArray(bbProductD, data);
callback(null);
},
});
}
The promises way, using jQuery.Deferred and jQuery.when
function getBBTrending() {
bbProductD = [];
jQuery.ajax({
//stuff...
success: function (data) {
bbTrending = data.results;
var promises = [];
for (var i = 0; i < bbTrending.length; i++) {
var promise = getProductdetails(bbTrending[i].productLink);
promises.push(promise);
}
jQuery.when.apply(jQuery, promises).then(function(){
displayProducts(bbProductD);
});
},
});
}
function getProductdetails(pLink) {
var promise = jQuery.Deferred();
jQuery.ajax({
//stuff
success: function (data) {
pushArray(bbProductD, data);
promise.resolve();
},
});
return promise;
}
The dirty way. I do not recommend this solution, it has many flaws. Try to use libraries when you need to do asynchronous stuff in order to keep your code maintainable.
var queriesCount, finishedQueriesCount;
function getBBTrending() {
bbProductD = [];
jQuery.ajax({
//stuff...
success: function (data) {
bbTrending = data.results;
queriesCount = 0;
finishedQueriesCount = 0;
for (var i = 0; i < bbTrending.length; i++) {
getProductdetails(bbTrending[i].productLink);
}
},
});
}
function getProductdetails(pLink) {
queriesCount++;
jQuery.ajax({
//stuff
success: function (data) {
pushArray(bbProductD, data);
finishedQueriesCount++;
if(queriesCount == finishedQueriesCount) {
displayProducts(bbProductD);
}
},
});
}
In each case, I pleaced the part of your code that is not significant for the answer by //stuff
Warning This answer has no error handling, it will fail (never call displayProducts(bbProductD);) if you have an ajax error.

Categories