jQuery AJAX stop request after another response - javascript

i have an issue and i need an idea for solve :)
I have 2 call to $.ajax
First, is asynch, and during a lot of time (1 minutes for example)
Second, is sync (in ajax async: false) and it response fast (5 sec for example)
Second call is in a loop (requests->response->print data, request->response->print data).
I need when first finish (success or error), stop second call.
I attach an example code:
var success = false;
$.ajax({
type: "POST",
url: urlRest,
data: {
data: dataSend
},
success: processOK,
error: processError
});
do {
$.ajax({
type: "POST",
url: urlData,
data: {
data: dataSend
},
async: false,
success: function(data, textStatus, jqXHR){
console.log(data);
},
error: function(data, textStatus, jqXHR){
console.log("Error");
}
});
} while (!success);
I hope it's clear :)

I corrected an issue that would cause some errors, try this out.
let printData = function( input ){
let config = {
urlRest: '',
data: { data: {} },
loop: false,
callback: false
}
$.each(config,function(k,v){ config[k] = input[k] });
config.loop = false;
$.ajax({
type: 'POST',
url: config.urlRest,
data: config.data,
success: function( data ){
// Based on the response if you need to run again change config.loop to true and it will run again
// you can also alter anything your sending through
if( config.loop ) printData( config );
else if( typeof config.callback === 'function' ) callback();
},
error: function(){
// Based on the response if you need to run again change config.loop to true and it will run again
// you can also alter anything your sending through
if( config.loop ) printData( config );
else if( typeof config.callback === 'function' ) callback();
}
});
}
printData({
urlRest: '', // URL Here
data: data, // Data Object
loop: true, // Set this to true if you want it to loop
callback: function(){
console.log( 'Job Complete' );
}
})

You can run async calls in synchronous manner using SynJS:
function ajaxWrapper(ctx, url, data){
var res={done:false};
$.ajax({
type: "POST",
url: url,
data: data,
success: function(result){
res.data=result;
},
error: function(){
res.error=true;
},
}).always(function(){
res.done = true;
SynJS.resume(ctx); // <-- tell caller that callback is finished
});
return res; // <-- return object that will hold the results
}
// function that is executed in synchronous manner
function myFunc(modules, urlRest, urlData) {
var success = false;
var res1 = modules.ajaxWrapper(_synjsContext, urlRest, urlData);
SynJS.wait(res1.done); // <-- wait for result from callback
do {
var res2 = modules.ajaxWrapper(_synjsContext, urlRest, urlData);
SynJS.wait(res2.done); // <-- wait for result from 2nd callback
} while (!success);
}
var modules = {ajaxWrapper: ajaxWrapper};
SynJS.run(myFunc,null, modules, "/", {}, function () {
console.log('done');
});

You can change the success value like this
$.ajax({
type: "POST",
url: urlRest,
data: {
data: dataSend
}
}).always(function() {success=true;});
Or you can create a self call function (after the second ajax finish, calls it again) but before the call its checks the success variable like #mplungjan did.

It is never a good idea to loop Ajax. You need to allow the call to return.
Here is an example that is NOT using async false
var firstDone = false,tId;
// call long ajax
$.ajax({
type: "POST",
url: urlRest,
data: {
data: dataSend
}
}).done(processOK);
}).fail(processError)
}).always(function() {firstDone=true; clearTimeout(tId);}); // stops the other loop
// setup function that can be looped
function callAjax() {
if (firstDone) return;
$.ajax({
type: "POST",
url: urlData,
data: {
data: dataSend
}
}).done(function(data, textStatus, jqXHR) {
console.log(data);
}).fail(function(data, textStatus, jqXHR) {
console.log("Error");
}).always(function() {
tId=setTimeout(callAjax,1000); // give the server time to recover
});
}
callAjax();

Related

Update element on every Ajax success response

I have a function that loops through an array and calls a php script for each object of the array. The php script is getting the Lat/Lng from google maps api so i need to throttle the api calls. The list can be long (currently 300). I want to update the user as the script is running.
In my success callback I can console log every response but the element I want to update for the user only gets updated once.
Is there a way to update the user after each successful response?
here is my function:
$('#agents-lat-lng').click(function() {
var data = {
'action': 'getLatLng'
}
$.ajax({
url: ajax_url,
type: 'post',
data: data,
dataType: 'json',
success: function(response){
for ( var i = 0, l = response.query.length; i < l; i++ ) {
$.when(updateLatLngDB(response.query[i]))
.done(function(dataFromResponses){
console.log('1 ', dataFromResponses[0])
}).fail(function(response){
console.error(response);
});
}
},
error: function (textStatus, errorThrown) {
console.log(textStatus, errorThrown)
}
})
})
Here is the second function:
function updateLatLngDB(query) {
var deferred = new $.Deferred()
var dataFromResponses = []
var count = 0
var data = {
'action': 'updateLatLng',
'agent': query
}
$.ajax({
url: ajax_url,
type: 'post',
data: data,
dataType: 'json',
cache: false,
async: false,
success: function(response){
count++
console.log('count ', count)
$('#process-upload-response').text(count)
dataFromResponses.push(response)
},
error: function (textStatus, errorThrown) {
console.log(textStatus, errorThrown)
deferred.reject(response)
$('#process-upload-response').html(textStatus, errorThrown)
}
})
deferred.resolve(dataFromResponses)
return deferred.promise()
}
I have tried everything from Deferred to setTimout but I can not get #process-upload-response to update as each item in the array gets processed. It only updates after all the responses are complete.
UPDATE: I have been able to make it work by adding this to the for loop
(function(i){
window.setTimeout(function(){
promises.push(updateLatLngDB(response.query[i],response.query.length));
}, i * 1000);
}(i));
The problem is that you don't keep state between calls to updateLatLngDB function and also you resolve the value with empty array because you don't call the resolve outside of async call.
If I understand this is what you want:
$.ajax({
url: ajax_url,
type: 'post',
data: data,
dataType: 'json',
success: function(response){
var promises = [];
var updateLatLngDB = countRequests(0);
for ( var i = 0, l = response.query.length; i < l; i++ ) {
// collect promises
promises.push(updateLatLngDB(response.query[i]));
}
// when all request are done execute done
$.when.apply($, promises).done(function() {
var dataFromResponses = arguments;
console.log('1 ', dataFromResponses[0])
}).fail(function(response){
console.error(response);
});
},
error: function (textStatus, errorThrown) {
console.log(textStatus, errorThrown)
}
})
// keep count in closure
function countRequests(count) {
return function updateLatLngDB(query) {
var deferred = new $.Deferred();
var data = {
'action': 'updateLatLng',
'agent': query
}
$.ajax({
url: ajax_url,
type: 'post',
data: data,
dataType: 'json',
cache: false,
async: false,
success: function(response){
count++
console.log('count ', count)
$('#process-upload-response').text(count)
dataFromResponses.push(response);
deferred.resolve(response);
},
error: function (textStatus, errorThrown) {
console.log(textStatus, errorThrown)
deferred.reject(response)
$('#process-upload-response').html(textStatus, errorThrown)
}
})
return deferred.promise()
};
}
NOTE: that if you don't want all request to be done in parallel you will need to create async loop I like to write them like this (with async/await it's simpler because you can create normal while loop instead):
var promises = [];
var i = 0; = response.query.length;
(function loop() {
if (i < len) {
var promise = updateLatLngDB(response.query[i++]);
promises.push(promise);
promise.then(loop);
} else {
$.when.apply($, promises).done(function() {
var dataFromResponses = arguments;
console.log('1 ', dataFromResponses[0])
}).fail(function(response){
console.error(response);
});
}
})();
with this you will be able to delay each request (if this is what you want).

Javascript - why is this undefined?

The alert at the start shows "undefined", why?
The alerts come in this order:
"success!"
"Data" (what it should be)
"undefined"
I read through multiple threads, the problem was always that ajax was asynchronous, so the data was not defined when it was accessed, but in my case the data is there, the alert in my function shows the data BEFORE the other alert where it is undefined!
Very grateful for any help!
I got this code
var data = getData("");
alert(data); <<<<<<< UNDEFINED
function getData(fileName) {
$.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
var arrData = processData(data);
alert("success!");
alert(arrData); <<<<< WORKS GREAT
return arrData;
},
});
}
function processData(data) {
var arrData = CSVToArray(data);
dimensions = arrData[0];
var objects = [];
objects[0] = dimensions;
for (var i = 1; i < arrData.length; i++){
objects[i] = new Object();
for (var j = 0; j < dimensions.length; j++){
objects[i][dimensions[j]] = arrData[i][j];
}
}
return objects;
}
To clarify, I know asynchronous is the way to go for user experience, but this page just has to show data from this call, so its okay for me to wait for it.
Your getData function doesn't return anything.
You need to return it from the function itself.
function getData(fileName) {
$.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
var arrData = processData(data);
alert("success!");
alert(arrData); <<<<< WORKS GREAT
return arrData;
},
});
}
^ This returns the data within getData. But getData doesn't do anything with it: such as returning it.
function getData(fileName) {
var ourData = "";
$.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
var arrData = processData(data);
ourData = arrData;
},
});
return ourData;
}
This returns the data from getData to whatever calls that function.
edit: also, don't use async:false. Your browser won't capture any events happening until that AJAX completes. The benefit of asynchronous JS is that...we can! And in this case should.
Preface: Don't use async: false. But answering the question:
getData doesn't return anything. You're doing a return from the success callback, but that returns something from the success callback, not getData.
To change it so getData returns something, you'd do this:
function getData(fileName) {
var arrData;
$.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
arrData = processData(data);
},
});
return arrData; // <=== Now `getData` returns something
}
But don't do that. Instead, embrace asynchronous programming and remove async: false. For instance, a callback:
function getData(fileName) {
$.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
callback(processData(data));
},
});
}
...called like this:
getData(function(data) {
alert(data);
});
...or a promise ($.ajax returns one, of sorts):
function getData(fileName) {
return $.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
callback(processData(data));
},
}).then(data) {
return processData(data); // <== Becomes the resolution value of `getData`'s promise
});
}
and then
getData().then(function(data) {
alert(data);
});
data is undefined because the function getData doesn't return anything. You should have a look at promises.

Wait until all my ajax functions are done, and then continue the execution for this i used async:false but it's not relative to performance

validateStepOneChannelData: function(callback)
{
var response = {error: false, data: {}};
var error = false;
var action = $("#action").val();
$.ajax({
type: "POST",
url: '/verifyEmailAddressByKickBox',
dataType: "json",
async:false,
data: ({email: $("#email").val()}),
beforeSend:function(){
$('#next_box1_button').prop('disabled', true).addClass('hy-loading-btn');
$('#saveChannel').prop('disabled', true).addClass('hy-loading-btn');
},
success: function(res) {
$('#next_box1_button').prop('disabled', false).removeClass('hy-loading-btn');
$('#saveChannel').prop('disabled', false).removeClass('hy-loading-btn');
if (res.status == 'F') {
error = true;
response.data.email = 'Please enter valid email address.';
}
}
});
if (error)
{
response.error = true;
}
callback(response);
I need to wait until all my ajax functions are done, and then continue the exectution for this i used async:false but it's not relative to performance. It is freezing browser for untill the ajax request.
How we used callback here to get the response first and execute the rest block..
Please advise.
This way can help you I'm sure
function ajaxCall(url,type,data = {}){
return $.ajax({
type:type,
url:url,
data:data
})
}
ajaxCall("url.php","post", {data:data} ).then(function(r){
// something what you need to do after ajax
})

ajax - return and prevent deferred.then() execution

I have a AJAX request like this:
$.ajax({
type: 'GET',
url: url,
dataType: "json",
success: function(data) {
// ...
callbak(true);
},
})
.then(
function( response ) {
// ...
});
I'd like to run that callback function and so exit from that ajax request in success function and prevent deferred.then() execution.
In my case the callback is fired but after that deferred.then() is also executed and I don't want this to happen.
Any idea?
Thanks
Use a flag like so:
var executeThen = true;
$.ajax({
type: 'GET',
url: url,
dataType: "json",
success: function(data) {
// ...
executeThen = false;
callbak(true);
},
})
.then(function(response) {
if(executeThen){
// ...
}
});

javascript parameters for callback

I have function which is call recursively by ajax complete callback, and I need to set parameters fot this function. But how do I transfer parameters in callback?
function poll(url, data, pollDelay, type){
$.ajax({ url: url, type: 'POST', data: data, success: function(data){
if(data != '' && type == 1) { //do answers
doOutput(data);
}
}, dataType: 'html', complete: pollTimeout = setTimeout('poll()', pollDelay), timeout: 30000 });
}
function doPoll() {
clearTimeout(pollTimeout);
poll('url/f.php', obj = { id: someId, data: somedata }, 10000, 1);
}
Thanks a lot
I'm assuming you're referring to your setTimeout call? Never pass a string to setTimeout.
pollTimeout = setTimeout(function() {poll(url,data,pollDelay,type);},pollDelay);
Note that your whole "complete" thing should be in such a function:
$.ajax({...
complete: function() {
pollTimeout = setTimeout(...);
}
...});

Categories