One function to wait for another function in Javascript (AJAX) - javascript

I'm trying to find a way to make one function to hold and only return its output (hold the flow) only when the async function inside it (AJAX call) have completed.
In this click event, the "prepareEstimates" function calls another function, which makes an AJAX call to an API. The ideia is that the code won't move forward until this function has completed everything there, including the AJAX call. Because it's calling the same API, I cannot have two simultaneous call using the same data (issues with the API that are out of scope from this question).
$('#estimateBtn').on("click", function () {
if (validateBasicEstimationForm()) {
prepareEstimates();
if (validateCustomEstimationForm()) {
prepareCustomEstimates();
}
});
function prepareEstimates() {
// check if runAPI should be true or false
if (runApi) {
// make call here
$.when(callAJAXFunction(path, dataForAPICalls)).done(function (result) {
// Do stuff with the result
});
}
};
Then, once this prepareEstimates function has completed, it should move forward and the next one, prepareCustomEstimates, which is very similar to this function, will do the same thing.
function prepareEstimates() {
// check if runAPI should be true or false
if (runApi) {
// make call here
$.when(callAJAXFunction(path, dataForAPICalls)).done(function (result) {
// Do other stuff with the result
});
}
};
and this callAJAXFunction just return an AJAX call
// Invoke API call and get result
return await $.ajax({
url: url,
type: "POST",
dataType: "json",
data: data,
success: function (result) {
},
error: function () {
console.log("error calling Api");
}
});
}
I tried using promise, await, and others, but I couldn't make it work, no matter what I tried.
In the end, what is happening is that the first AJAX call is fired, then right after it, the second ajax call, before the first one has completed.
Any suggestion?
Thank you

Related

Collect html form data and send as a json payload to an api [duplicate]

I got following code :
$.ajax({
type: "POST",
async: false,
url: "CheckIdExist",
data: param,
success: function(result) {
if (result == true){
return false;
}
},
error: function(error) {
alert(error);
return false;
}
});
if ajax return value is true, form needs to stop submit.
but it does not stopping submit form.
any help please.
I assume you have something like:
form.submit(function(event) {
$.ajax(...);
});
You want to return false (or call event.preventDefault()) in the event handling function itself, and not in the AJAX call, such as:
form.submit(function(event) {
event.preventDefault();
$.ajax(...);
});
A slight variation of this question is:
I want to use jquery and ajax to present an error message to a user,
but then to do normal processing if there is no error.
Suppose method "check" returns a response that is empty if there is no error, and has the error(s) in it if there are any.
Then you can do something like this in your ready function:
$("#theform").submit(function() {
var data = { ... }
$.get('/check', data,
function(resp) {
if (resp.length > 0) {
$("#error").html(resp);
} else {
$("#theform").unbind('submit');
$("#theform").submit();
}
});
event.preventDefault();
});
So, how does it work? When the outer submit function is triggered, it builds the data needed for the AJAX call (here the higher level function get). The call is scheduled, and the main thread of operation immediately continues, but the submit is unconditionally stopped, so nothing apparent happens.
Some time passes, and the AJAX call returns the result of the request. If non-empty, the result is shown to the user.
If the response is empty, however, the submit function is unbound. This prevents the ssytem from making an extra call through the outer submit function. The inner submit function is called. This triggers an actual form submission to the form's target, and life goes on as expected.
You need to do a callback.
This entry in the FAQ helped me a lot when I had this exact problem.
getUrlStatus('getStatus.php', function(status) {
alert(status);
});
function getUrlStatus(url, callback) {
$.ajax({
url: url,
complete: function(xhr) {
callback(xhr.status);
}
});
}
The reason for that is that you can not return in an AJAX function.
The code above does not work as desired due to the nature of asynchronous programming. The provided success handler is not invoked immediately, but rather at some time in the future when the response is received from the server. So when we use the 'status' variable immediately after the $.ajax call, its value is still undefined.
You can't put this code in a function or in the onsubmit of a form, the success function returns it's result returning to the jQuery ajax context, NOT the form submit context.
In this case you need to perform a synchronous http request, i.e. you have to set the async option to false.
In your version the httpxmlrequest is asynchronous. It might be finished long after your onsubmit handler has returned and the onsuccess callback is invoked out of context of the onsubmit handler.
The "return false" will be the return value of the anonymous function function(result) {... } and not the return value of the onsubmit handler.
I had this problem also but solved it by changing the input type="submit" to type="button" and then just do your ajax request
$("input#submitbutton")
{
$.ajax(
{ type: "POST",
async: false,
url: "CheckIdExist",
data: param,
success: function(result) {
if (result == true){
//TODO: do you magic
}
else
$("form").submit();
},
error: function(error) {
alert(error);
return false;
}
});
});

angularjs - Sequentially call function that performs ngResource http post request

This is the outline of a function to perform and http post request to get all the entries from a table. This function is defined within my controller.
$scope.getAllData = function (tableName) {
var allDataResults = $resource('/getAllDataForTable', {}, {
save: {
method: 'POST',
timeout: 6000
}
});
allDataResults.save($scope.all_data_input, function (response) {
//Do stuff with response
}
});
};
I need to call this function sequentially for different tablenames. I tried simply calling it twice like this.
$scope.getAllData(tableName1);
$scope.getAllData(tableName2);
The second response comes in correct, but the first one is incorrect. Each response contains a list and the size of the second response's list is forced on the first one, causing the response to be incorrect. How do I properly chain these 2 post requests requests?
You need to return the promise from your function, i. e.:
$scope.getAllData = function (tableName) {
var allDataResults = $resource('/getAllDataForTable', {}, {
save: {
method: 'POST',
timeout: 6000
}
});
return allDataResults.save($scope.all_data_input, function (response) {
//Do stuff with response
}
});
};
Then, you can chain your calls using the returned promise:
$scope.getAllData(tableName1).$promise.then(function() {
$scope.getAllData(tableName2);
});
Btw the $resource examples might help you understand it better. If you need to manage a lot of chained promises, you should look at $q.all.

Nested Ajax Call not getting executed [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I am making nested Ajax call, here is code for that:
function getCheckListId() {
var authToken = getCookie("aqs_authToken");
//Lets say AjaxCall1
$.ajax({
....
// Basic Ajax definition (type, url, etc.....)
....
success: function (result) {
for (var i=0; i< result.length;i++) // ForLoop AjaxCall1
{
var sample= result[i].checklistDetailId;
// Lets say AjaxCall2
$.ajax({
url: 'URL' +sample
// Code for Another Ajax Call
success: function(result) {
for(var i=0; i<result1.length; i++) { { ... Some code.. }
} // END ForLoop AjaxCall2
toSendEmail();
// This is function call in which I am posting data (AjaxCall3)
}, // Success Function close for AjaxCall2
error: function(error) {.. some code.. }
} // Error function close for AjaxCall2
}
}); // Close of AjaxCall2
}, // Success Function close for AjaxCall1
error: function (error) {
alert("Some Statement");
} // Error Function Close for AjaxCall1
});
}
I am making AjaxCall2 in AjaxCall1' Success function. But my AjaxCall2 is not getting executed it is directly making the call to function toSendEmail()
I had look around and I tried like making function inside function (nested function) to make my ajax call executed but still not working.
Can anyone suggest me any another way to execute it? or What I need to change to get my AjaxCall2 executed BEFORE controller calls toSendEmail() method?
Thank You
toSendEmail() needs to go inside:
success: function(result) { ... Some code.. },.
Otherwise it will run before your second ajax call has returned. You are correctly calling the second ajax call in the success handler of the first, now you just need to put your final step inside the success handler of the second ajax call.

jQuery When Done on dynamically pulled function call

I have the following code:
In site-code.js
....
var ajaxContentFunc = $(origin).data("modal-content-handler");
$.when(window[ajaxContentFunc]()).done(function (resp) {
kModal.showContent(resp);
});
In another file I have the following tag and function
Click Me
....
function ajaxContentGeneration() {
var aProm = $.ajax({
url: "tests/ajax/AjaxTest.aspx",
data: { exampleType: "modal-ajax" },
dataType: "html"
});
aProm.done(function (data) {
console.log("Ajax Loaded!");
var content = $(data).find("#ajax-content");
return aProm;
});
}
I need to populate the result of the ajaxContentGeneration (whatever method that might be) into the variable to send to showContent or in other words:
1) Pull the ajaxContentFunction Name from the tag's modal-content-handler data attribute
2) Call function (in this case ajaxContentGeneration)
3) Wait for the function's ajax to complete and return the data generated (in this case html)
4) When completed pass that value to kModal.showContent(----Here----);
However currently I am getting:
1) Pulls ajaxContentFunctionName correctly
2) Calls Function (ajaxContentGeneration() function)
3) Calls kModal.showContent(undefined). This is called prematurely because the deferred isn't correctly waiting for the function call to complete (after the ajax is done).
4) Ajax Completes
Where am I messing up here ?
As far as I can tell, you are 95% there.
Use .then() instead of .done() and return the promise returned by $.ajax().then() :
function ajaxContentGeneration() {
return $.ajax({
url: "tests/ajax/AjaxTest.aspx",
data: { exampleType: "modal-ajax" },
dataType: "html"
}).then(function (data) {
return $(data).find("#ajax-content"); // this will return jQuery
// return $(data).find("#ajax-content").html(); // this will return html
});
}
You can probably also purge $.when() from the top-level call :
var ajaxContentFunc = $(origin).data("modal-content-handler");
window[ajaxContentFunc]().then(function (resp) {
// `resp` is whatever was returned by the `return $(data).find()...` statement above
kModal.showContent(resp);
});
The reason I say "probably" is that $.when() would be necessary if value-returning (not promise-returning) functions could be called instead of ajaxContentGeneration().
Another way would be to do:
// should really be renamed...
function ajaxContentGeneration(){
return $.ajax({
url : "tests/ajax/AjaxTest.aspx",
data : { exampleType: "modal-ajax" },
dataType : "html"
})
}
Somewhere else:
var ajaxContentFunc = $(origin).data("modal-content-handler");
window[ajaxContentFunc]()
.done(function(RES){
kModal.showContent( $(RES).find("#ajax-content") );
});
So the functionality of the ajaxContentGeneration function will be to return an AJAX promise, and not have it manipulated inside it, but do the manipulation where needed (getting the #ajax-content element from the response)
Note that this whole thing is bad practice JS design, and you should avoid having functions on top of the window object, but instead on another object.

js variable scope question

how do i make data overwrite results variable ?
var ajax = {
get : {
venues : function(search){
var results = "#";
$.getJSON("http://x.com/some.php?term="+search+"&callback=?",function(data){ results = data; });
return results;
}
}
};
data is overwriting results, just after results has been returned.
You can use the ajax function instead of getJSON, since getJSON is just shorthand for
$.ajax({
url: url,
dataType: 'json',
data: data,
success: callback
});
and then also set async to false, so that the call will block.
However, in your case this won't work, because JSONP requests (with "?callback=?") cannot be synchronous.
The other (better) option is to have whatever code is dependent on the results return value get called by the success callback.
So, instead of something like this:
var results = ajax.get.venues('search');
$('#results').html(translateResults(results));
Maybe something like this:
ajax.get.venues('search', function (results) {
$('#results').html(translateResults(results));
});
venues = function (search, callback) {
$.getJSON("http://x.com/some.php?term="+search+"&callback=?",
function(data){
callback(data);
});
};
Your problem is the asynchronous nature of JavaScript. results does get overwritten, but only later, after the function has already exited, because the callback is executed when the request has finished.
You would have to make the Ajax call synchronous using sync: true (this is usually not a good idea, just mentioning it for completeness's sake) or restructure your code flow so it doesn't depend on the return value any more, but everything you need to do gets done in the callback function.
This isn't a scope problem. It's because $.getJSON is asynchronous; results is returned before $.getJSON finishes. Try making a callback for $.getJSON to call when it's done.
function JSON_handler(data){
// do stuff...
}
$.getJSON("http://x.com/some.php?term="+search+"&callback=?", JSON_handler);
You could put the logic you want to run in a callback.
var ajax = {
get : {
venues : function(search, fnCallback){
var results = "#";
$.getJSON("http://x.com/some.php?term="+search+"&callback=?",
function(data){
// success
results = data;
(typeof fnCallback == 'function') && fnCallback(data);
});
return results;
}
}
};
ajax.get.venues(term, function(result){
// Do stuff with data here :)
})
functional programming can be fun.

Categories

Resources