Wait for AJAX response before moving on with script - javascript

I have a script which runs 2 AJAX calls, the first checks that a record exists within a database. If it does this should not move on and the script should stop. The second submits a job.
My problem is that the job is being submitted before the first AJAX call has returned. My code looks something like this:
if (recordid) {
var request = $.ajax({
context: document.body,
url: URLGOESHERE,
data: {
recordID: recordid
},
success: function( data ){
if (data.Response == "Success") {
var noresults = data.Results;
if (noresults > 0){
alert('this record id already exists!');
return false;
}
} else {
alert('an error occured');
return false;
}
}
});
} else {
alert('enter a record id');
return false;
}
// second ajax call goes here, which gets called regardless of the output of the ajax call above

Instead of putting the call to the second ajax method at the bottom of your code (where the comments currently are), put it in the "success" function of your first call. This method will only execute once the first call has finished. This is the only way to ensure that the second call does not happen too early. Ajax calls run asynchronously, so the normal flow of the browser is not interrupted. This is deliberate so that long-running calls don't lock up the browser for the user.

if (recordid) {
var request = $.ajax({
context: document.body,
url: URLGOESHERE,
data: {
recordID: recordid
},
success: function(data) {
//check here if you want to call submitJob or not
//and call submitJob()
}
});
} else {
alert('enter a record id');
return false;
}
//call this ajax once you varified your condition from success callback of first one
function submitJob() {
//second ajax call goes here
}

You have to use jquery promise function for that which will wait for the first ajax request to complete then make another ajax request.
JQUERY PROMISE
OR
Put the second ajax request in the success function of first one, and make it happen when you want it to fire
if (recordid) {
var request = $.ajax({
context: document.body,
url: URLGOESHERE,
data: {
recordID: recordid
},
success: function(data) {
//check here if you want to call submitJob or not
if (noresults > 0){ return false }
else { Job(); };
}
});
} else {
alert('enter a record id');
return false;
}
function Job() {
//another ajax call.
}
Hope it helps :)

try this: make async propety false
if (recordid) {
var request = $.ajax({
context: document.body,
url: URLGOESHERE,
data: {
recordID: recordid
},
async : false, //added this
success: function( data ){
if (data.Response == "Success") {
var noresults = data.Results;
if (noresults > 0){
alert('this record id already exists!');
return false;
}
} else {
alert('an error occured');
return false;
}
}
});
} else {
alert('enter a record id');
return false;
}
OR
perform second ajax call in success function of first ajax call i.e. see comment
if (recordid) {
var request = $.ajax({
context: document.body,
url: URLGOESHERE,
data: {
recordID: recordid
},
success: function( data ){
if (data.Response == "Success") {
var noresults = data.Results;
if (noresults > 0){
alert('this record id already exists!');
return false;
}
//perform 2nd ajax call here
} else {
alert('an error occured');
return false;
}
}
});
} else {
alert('enter a record id');
return false;
}

Related

Success function not working based on submit

I have a Ajax call that is working, but the success function isn't. I have a a few dates that I am inputting, after hitting submit, there should be a little alert popup saying "Data saved to the DB". The data is getting saved to the DB, however I am not getting the popup alert window.
$("#btnSubmit").bind("click", function () {
createUpdateArrays();
var url = "/Sample/Selection";
$.ajax({
type: "GET",
url: url,
data: { ids: ids, dates: dates },
success: function (success) {
if (success === true) {
alert("Success");
}
else {
alert("error");
}
}
});
ids = "";
dates = "";
});
function createUpdateArrays() {
var i = 0;
$('input.remedy-id:checkbox').each(function () {
if ($(this).is(':checked')) {
var rid = $(this).attr("id");
$('.planned-date').each(function () {
var did = $(this).attr("id");
if (did === rid) {
var date = $(this).val();
ids += rid + ",";
dates += date + ",";
}
});
};
});
};
I can't seem to understand the reason behind this..
EDIT: Before doing ANYTHING else, make sure that your server is actually returning a response to begin with.
Your success function is expecting a boolean to be returned by the server, but this is probably not what is happening. If you're returning a simple string "success" from the server, then the comparison should be if (success === "success"). This is entirely dependent on what your server is returning as a response.
Perhaps your server is returning a status code of 2xx. In either case, you can use the jQuery status code callbacks:
$.ajax({
type: "GET",
url: url,
data: { ids: ids, dates: dates },
statusCode: {
200: function(){alert("Success!")},
201: function(){alert("Success!")}
}
});
And if you don't want to do that and just want to use the success callback, try something like this:
success: function (success) {
if (success || (success.length && success.length == 0)) { // this will almost definitely evaluate to true
console.log(success) // Do this to see what is actually being returned. I guarantee it isn't a boolean value.
alert("Success");
}
else {
alert("error");
}
}

Javascript program not executing correctly

I'm new to javascript, but I can't get my head around this problem. I have a function that upvotes a game:
function upVoteGame(name) {
$.get("/get_gameValues", function(data) {
var alreadyExist = false;
var noVotes = false;
var games;
games = data;
for (var i = 0; i < games.length; i++) {
if (name === games[i].gameName) {
alreadyExist = true;
voteOperations();
if (userLoggedIn == false) {
alert("second");
swal("Cannot post votes", "Please log in or register to vote", "error");
}
if (noVotesLeft == false && userLoggedIn == true) {
$.ajax({
url: '/editVotes/' + games[i]._id,
type: 'PUT',
data: {
likes: games[i].likes + 1,
totalVotes: data[i].totalVotes + 1
},
success: function(result) {
alert(games[i].likes + 1);
}
});
}
refreshGameValues();
break;
}
}
//This is for us Developers!
if (!alreadyExist) {
$.post("/add_game_to_dB", {
gameName: name
}, function(result) {
alert("Introduced " + name);
});
}
});
}
Now I have the function that updates the user's votes left, voteOperations():
function voteOperations() {
$.get("/users/get_current_user", function(data) {
//var votes = 5;
for (var i = 0; i < data.length; i++) {
votesRemaining = data[i].votesRemaining;
userLoggedIn = true;
alert("votes left : " + votesRemaining);
if ((votesRemaining - 1) < 0) {
swal("No votes remaining", "Please wait 24 hours to get more votes", "error");
noVotesLeft = true;
}
if (noVotesLeft == false) {
$.ajax({
url: '/users/updateUserDetails/' + data[i].user_name,
type: 'PUT',
data: {
votesRemaining: votesRemaining - 1
},
success: function(result) {}
});
}
}
});
}
My problem is a simple problem. In the upVoteGame(name) function, I want the voteOperations() to execute before the if loop below it. However, when I run the code, the if loop below executes first and alerts the user that they are not logged in. When a user logs in, userLoggedIn is set to true, but the if loop executes firsts and tells them that they are not logged in, and then executes the voteOperations() function. I don't know why this is happening. How can I fix this so that voteOperations executes before the if loop?
This is because the voteoperations function has a get request which is asynchronous. You will need a callback function where you should include if condition
You can try:
function upVoteGame(name) {
vote(afterGet);
}
afterGet() {
if condition here
}
function vote(callback) {
$.get .... {
//after getting data
callback();
}
}
You problem occurs due to the asynchronous call of your $.get in the voteOperations function.
Since it is an asynchronous call your code continuous while your $.get is waiting to retrieve data and thus your if statement seems to trigger before your voteOperations function.
In simple words your function actually is triggered before the if statement but before it completes it's result the code continues and triggers your if statement.
You could put your if statement (logic) in the success callback of your vote operation function or use $.ajax with async:false which is not considered a good practice generally but I use it sometimes.
Something like that for example (for the second case)
$.ajax({
async: false,
.....
success: function (response) {
//
}
});
Asynchronous calls can be handled with jquery function Deffered
function upVoteGame(name) {
vote().then(doUpVoteGame(), handleError());
}
function doUpVoteGame() {
...
}
function handleError(e) {
console.error("fail", e);
}
function vote() {
var d = new $.Deferred();
$.get .... {
d.resolve();
}).fail(function(e) {
d.reject(e);
});
return d;
}

how do i wait for multiple ajax calls to complete from a .each loop

I am running a loop that updates records on a table but i need to wait for all of the records to update before i continue on.
How can I have jquery wait until all of the calls in the loopselectedrows function completes? I have read about .deferred and .when but i am not sure how to implement
either. they both do not seem to able to handle an array of calls if i where to change over to using an array for the ajax posts. Any help would be greatly appreciated.
this is the button that starts it all :
click: function () {
// validate all rows
var $selectedRows = $('#Table1').jtable('selectedRows');
LoopSelectedRows($selectedRows, 'Validate');
/// wait here until all ajax calls have completed
// then continue with checking
// check for any row with an error
var $ValidatedRows = $('#Table1').jtable('selectedRows');
var boolCheck = checkValidatedRows($ValidatedRows);
// if all records are succesfull then add them
// else alert user
if (boolCheck == true) {
LoopSelectedRows($selectedRows, 'Add');
}
else {
alert("Please correct invalid records and try again");
}
}
the first thing this does is take all of the records from the table and passes them to a looping function.
this is the looping function -
function LoopSelectedRows(SelectedRecords, actionType) {
if (SelectedRecords.length > 0) {
//Show selected rows
SelectedRecords.each(function () {
var record = $(this).data('record');
record.PERSON_NAME = record.PERSON_ID;
// Actions for loop
// Validation Action
if (actionType == 'Validate') {
check = validateRecord(record);
}
// call add function
if (actionType == 'Add') {
AddRecordToTable(record);
}
})
};
}
this loop can either validate or add records for now i am only worried about the validation function
this is the validation function:
function validateRecord(dataRecord) {
$.ajax({
url: "./ValidateAddRecord",
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(dataRecord),
success: function (data) {
if (data.Result == "OK") {
// update record with message
$('#table1').jtable('updateRecord', { record: data.Record });
}
else {
// display error
alert(data.Message);
}
}
});
}
One fairly clean way to know when multiple ajax calls are done is to use promises and jQuery's $.when(). That will give you a callback when all the ajax calls are done. It will take a little bit of reorganization of your code to use that.
First, you return the $.ajax() promise from validateRecord():
function validateRecord(dataRecord) {
return $.ajax({
url: "./ValidateAddRecord",
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(dataRecord),
success: function (data) {
if (data.Result == "OK") {
// update record with message
$('#table1').jtable('updateRecord', { record: data.Record });
}
else {
// display error
alert(data.Message);
}
}
});
}
Then, you collect all the promises in LoopSelectedRows() and return a master promise using `$.when():
function LoopSelectedRows(SelectedRecords, actionType) {
var promises = [];
if (SelectedRecords.length > 0) {
//Show selected rows
SelectedRecords.each(function () {
var record = $(this).data('record');
record.PERSON_NAME = record.PERSON_ID;
// Actions for loop
// Validation Action
if (actionType == 'Validate') {
promises.push(validateRecord(record));
}
// call add function
if (actionType == 'Add') {
promises.push(AddRecordToTable(record));
}
})
};
// return master promise
return $.when.apply($, promises);
}
Then, you can use that final promise to know when everything is done.
click: function () {
// validate all rows
var $selectedRows = $('#Table1').jtable('selectedRows');
LoopSelectedRows($selectedRows, 'Validate').then(function() {
// all the ajax calls in LoopSelectRows are done now
// check for any row with an error
var $ValidatedRows = $('#Table1').jtable('selectedRows');
var boolCheck = checkValidatedRows($ValidatedRows);
// if all records are succesfull then add them
// else alert user
if (boolCheck == true) {
LoopSelectedRows($selectedRows, 'Add');
} else {
alert("Please correct invalid records and try again");
}
});
FYI, you probably also want to change AddRecordToTable() to return a promise so it can work the same way (though it is not required because you aren't trying to wait for that operation to be done).
$.active returns the number of active Ajax requests. Use $.active==0 means no ajax requests are active. You could also use ajaxStart and ajaxStop to keep track of when requests are active.
Thank you jfriend00, your solution seems to have solved my issues.
Below is the updated version i am now using for anyone interested :
click: function () {
// validate all rows
var $selectedRows = $('#table1).jtable('selectedRows');
LoopSelectedRows($selectedRows, 'Validate').then(function () {
// check for any row with an error
var $ValidatedRows = $('#table1).jtable('selectedRows');
var boolCheck = checkValidatedRows($ValidatedRows);
// if all records are succesfull then add them
// else alert user
if (boolCheck == true) {
LoopSelectedRows($selectedRows, 'Add');
}
else {
alert("Please correct invalid records and try again");
}
});
}
// loop function
function LoopSelectedRows(SelectedRecords, actionType) {
var promises = [];
if (SelectedRecords.length > 0) {
//Show selected rows
SelectedRecords.each(function () {
var record = $(this).data('record');
// Actions for loop
// Validation Action
if (actionType == 'Validate') {
promises.push(validaterecord(record));
}
// call add function
if (actionType == 'Add') {
AddRecordToTable(record);
}
})
};
return $.when.apply($, promises);
}
// validate function
function validaterecord(dataRecord) {
var def = $.Deferred();
$.ajax({
url: "./ValidateAddRecord",
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(dataRecord),
success: function (data) {
if (data.Result == "OK") {
// update record with message
$('#table1).jtable('updateRecord', { record: data.Record });
// resolve token
def.resolve();
}
else {
// display error
alert(data.Message);
}
}
});
return def.promise();
}

how to break execution and display error inside success of ajax?

I am using ajax call to check for some validation and then submitting the form normally by html. In my ajax call,
function checkId() {
var str = $("#formObj").serialize();
$.ajax({
type : "post",
data : str,
url : "checkForId.mt",
async : false,
success : function(txt) {
if (txt == "pass") {
return "true";
} else if (txt == "same") {
$("#errorMsgIdSame").removeClass("hidden");
return "false";
}
},
error : function() {
alert("Error");
}
});
}
If the control goes to "pass", execution should continue. If it goes to "same", the execution should stop.
I am calling this ajax method from some other method.
function validateForm() {
var isValid = true;
isValid = checkId();
if (!isValid) {
$("#errorMsg").removeClass("hidden");
}
return isValid;
}
this validatioForm is called on button click. Now ajax code is working but validateForm method is not taking the return of the ajax method.
Need direction on how to carry this out so that to capture the return from the ajax method and how to return from the ajax method.
If I understood your question correctly, you want to return the result of an inner function from an outer function. This definition of checkId does just that.
function checkId() {
var result;
var str = $("#formObj").serialize();
$.ajax({
type : "post",
data : str,
url : "checkForId.mt",
async : false,
success : function(txt) {
if (txt == "pass") {
result = true;
return;
} else if (txt == "same") {
$("#errorMsgIdSame").removeClass("hidden");
result = false;
return;
}
},
error : function() {
alert("Error");
}
});
return result;
}
An ajax call is asynchronous.
When you call ajax what is happening is that the ajax starts a new thread to do its task--a post in your case.
After that the code that called the ajax keeps going.
When the task that the ajax call is doing returns, it executes what ever is in its pass or fail sections depending on the task status.
So basically your checkId method completes and returns before the ajax is finished.
I would recommend triggering whatever you need the return value for from the success section or fail section like this:
success : function(txt) {
if (txt == "pass") {
newfunction(true);
} else if (txt == "same") {
$("#errorMsgIdSame").removeClass("hidden");
newfunction(false);
}
},
Edit:
function newfunction(passFail)
{
//Do something with variable passFail
}

What design pattern should I apply when checking multiple ajax request completion?

I have 3 ajax call in one function and checkAjaxCompletion which checks each ajax completion flag.
What the code below does is send multiple separate ajax calls and interval method checks completion flags to determine whether to proceed or keep interval. (I know clearInterval is not shown but the point is I want to use something other than interval)
Current code is:
function manyAjax() {
setInterval( function() { checkAjaxCompletion(); } , 200);
ajax1();
ajax2();
ajax3();
}
function ajax1() {
//send ajax request to server and if success set flag to 1. Default is 0. Error is 2.
}
function ajax2() {
//send ajax request to server and if success set flag to 1. Default is 0. Error is 2.
}
function ajax3() {
//send ajax request to server and if success set flag to 1. Default is 0. Error is 2.
}
function checkAjaxCompletion() {
if(ajax1_flag == 1 && ajax2_flag == 1 && ajax3_flag == 1) {
//everything went success, do some process
}
else if(ajax1_flag == 2 || ajax2_flag == 2 || ajax3_flag == 2) {
//some ajax failed, do some process
}
else {
//all ajax have not been completed so keep interval i.e. do nothing here
}
}
But I'm hesitating to depend on using interval function because calling it so often seem such waste of memory. There must be better way to do. I'm thinking if observer pattern can be applied here but would like to hear opinions.
It is observer-notifier, if you want to call it that - but each of your ajax calls will more than likely have a callback in javascript when they complete. Why not call checkAjaxCompletion() at the end of each of them, and do nothing if you're still waiting on others?
Dustin Diaz does a great job with this example.
function Observer() {
this.fns = [];
}
Observer.prototype = {
subscribe : function(fn) {
this.fns.push(fn);
},
unsubscribe : function(fn) {
this.fns = this.fns.filter(
function(el) {
if ( el !== fn ) {
return el;
}
}
);
},
fire : function(o, thisObj) {
var scope = thisObj || window;
this.fns.forEach(
function(el) {
el.call(scope, o);
}
);
}
};
The publisher:
var o = new Observer;
o.fire('here is my data');
The subscriber:
var fn = function() {
// my callback stuff
};
o.subscribe(fn);
To unsubscribe:
var fn = function() {
// my callback stuff
};
o.subscribe(fn);
// ajax callback
this.ajaxCallback = function(){
$.ajax({
type: "POST",
url: ajax.url,
data: {key: value},
async : !isAll,// false使用同步方式执行AJAX,true使用异步方式执行ajax
dataType: "json",
success: function(data){
if(data.status == 'successful'){
selfVal.parent().find('.msg').addClass('ok').html(msg.ok);
}else if(data.status == 'failed'){
checkRet = false;
selfVal.parent().find('.msg').removeClass('ok').html(msg.error);
}else{
checkRet = false;
}
return this;
}
});
}
return this;
Maybe you want to check your inputvalue callback ajax in your form;
You can view my website Demo, hope help you.
http://6yang.net/myjavascriptlib/regForm
Okay my idea was to make your own object that can handle sending an array of requests, keep a history of each request and do what i'm gonna call 'postProccessing' on each response, here is a probably very dodgy bit of code to hopefully demonstrate what I am thinking.
var Ajax = function() {
var request, callback, lst;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else if (window.ActiveXObject) {
request = new ActiveXObject("Microsoft.XMLHTTP");
}
request.onreadystatechange = handleResponse;
this.history = [{}];
this.send = function(args) {
for (var i = 0; i < args.length; i++) {
if (args.url) {
request.open(args.type || 'GET', args.url);
}
request.send(args.data || null);
callback = args.callback;
lst++;
}
}
function handleResponse() {
var response = {
url: '',
success: true,
data: 'blah'
};
history.push(response);
if (postProccess()) {
callback();
}
}
function postProcess() {
if (this.history[lst].success) {
return true;
} else {
return false;
}
}
}

Categories