jquery ajax deferred object not returning value - javascript

I have this code..
if (!checkIfCustomerIsValid(event)) {
event.preventDefault();
return false;
}
else {
AddCustomer();
}
function checkIfCustomerIsValid(event) {
if ($('#txtCName').val() == '') {
alert('Please enter a valid value for customer name!');
return false;
}
if ($('#txtCAddress').val() == '') {
alert('Please enter a valid value for customer address!');
return false;
}
}
It returned fine, until then, but I added a new check and its not returning anything.
function checkIfCustomerIsValid(event) {
// code that was already there, the name and address check
var _mobNo;
if ($('#txtMobile').val() == '') return false;
var _unq = $.ajax({
url: '../Autocomplete.asmx/IsMobileUnique',
type: 'GET',
contentType: 'application/json; charset=utf8',
dataType: 'JSON',
data: "mobileNo='" + $('#txtMobile').val() + "'",
async: false,
timeout: 2000,
success: function (res) { if (res.d) return false; else return true; },
error: function (res) { alert('some error occurred when checking mobile no'); }
}),chained = _unq.then(function (data) { if (data.d == false) { alert('mobile no already exists!'); $('#txtMobile').focus(); return false; } return true; });
}
If mobile no is not unique the alert shows fine that mobile no is not unique, but when it is unique the code doesn't go into AddCustomer (in the else part)??? Is it not returning true? Why is it not going into AddCustomer???

With your new test, checkIfCustomerIsValid is asynchronous. There is no way for it, even with deferred, to directly return the result of a distant call.
The simplest here would be to pass a callback to your checkIfCustomerIsValid function or to return the promise from the function. As you mix synchronous and asynchronous tests, the best would be to pass a callback to checkIfCustomerIsValid.

You're correct, there is not a scenario where checkIfCustomerIsValid would return true. This is because you're attempting to return true from an anonymous function (i.e. a callback after the ajax request). When you return true from
chained = _unq.then(function (data) { if (data.d == false) { alert('mobile no already exists!'); $('#txtMobile').focus(); return false; } return true; });
You're only returning from that anonymous function, not from checkIfCustomerIsValid. Solving this problem is not completely straight forward and is an issue created from the nature of asynchronous calls. The most common solution to this is to pass a callback to your asynchronous call. Here is a fiddle which implements this.
http://jsfiddle.net/p3PAs/

Ajax is asynchronous and won't block, so the return value is most likely undefined. You can modify the code to something like the following:
success: function (res) { if (res.d) callRoutineToAddCustomer(); },

Related

how to stop function processing until the ajax call complete? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
see I have code like this
function validate(){
if (document.getElementById('<%=txtSeqNo.ClientId %>').value.trim() == "") {
alert('Please enter Seuenceqnumer.');
return false;
}
var result = checkduplicateseq();
if (result) {
return true;
}
else {
return false;
}
}
and definitation for checkduplicateseq is
function checkduplicateseq() {
var result = true;
if ($('[id*=ctl00_CPHMainPageLambda_chkoperationlist] input[type="checkbox"]:checked').length > 0) {
var seqNo = $("#ctl00_CPHMainPageLambda_txtSeqNo").val();
var chkvalue = $('[id*=ctl00_CPHMainPageLambda_chkoperationlist] input[type="checkbox"]:checked').parent().parent().find("span").attr("datavalue");
var hfmode = $("#ctl00_CPHMainPageLambda_hd_SequenceNo").val();
var oldoperationid = $("#ctl00_CPHMainPageLambda_hd_operationo").val();
if (seqNo == "") {
}
else {
$.ajax({
type: "POST",
url: "frmFAQMst.aspx/GetSequenceNoforOperation",
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: '{"OptionaId":"' + chkvalue + '","oldoperationid":"' + oldoperationid + '","seqNo":"' + seqNo + '","hfmode":"' + hfmode + '"}',
error: function (ex) {
console.log(ex);
},
success: function (response) {
if (response.d == "1") {
alert("Sequence Number already exist!");
$("#ctl00_CPHMainPageLambda_txtSeqNo").attr('value', '')
$("#ctl00_CPHMainPageLambda_txtSeqNo").focus();
result = false;
}
else {
result = true;
}
}
});
}
}
return result;
}
now if i call checkduplicateseq from validation function at the last
and store return value of checkduplicateseq fucntion in variable like
var result = checkduplicateseq();
in browser i can see the value of result = undefine
so it goes to else part of that function
if (result) {
return true;
}
else {
return false;
}
and in it return false so further execution not work
i want to go further after finishing checkduplicateseq (ajax call)
use a callback in your success function. you can pass the callback into your checkduplicateseq function, or just leave it in the global namespace and call it directly from your success function, or you can just inline that function altogether (defined inside success function)
checkduplicateseq(someCallback);
function someCallback () {
return !!result
}
and your success function
success: function(response) {
if (response.d == "1") {
alert("Sequence Number already exist!");
$("#ctl00_CPHMainPageLambda_txtSeqNo").attr('value', '')
$("#ctl00_CPHMainPageLambda_txtSeqNo").focus();
result = false;
} else {
result = true;
}
someCallback();
}
The best way, if you're chaining lots of callbacks, is to research Promises, which allow you to write in a sequential fashion, rather than passing things to be invoked later
You can add the option of async: false to the $.ajax() function which will cause the process to wait. This is generally considered bad practice though.
e.g.
$.ajax({
async: false,
type: "POST",
url: "frmFAQMst.aspx/GetSequenceNoforOperation",
contentType: 'application/json; charset=utf-8',
dataType: 'json',
.... etc
I was checking on this issue i just found a similar question in stack overflow. Please check this link
How to do sequential asynchronous ajax requests with given number of streams

javascript function inside jquery foreach loop doesn't wait for response

My foreach loop:
jQuery(".custom-checkbox").each(function() {
if (jQuery(this).attr('data-action') == 'true') {
if(deleteQuoteItemFromListing(jQuery(this).attr('data-id'))){
console.log('passed');
}else{
console.log('failed');
}
}
});
And the function is(It's using prototype) but it successes
function deleteQuoteItemFromListing(id){
//does someoperations and on success
delurl = getDelUrl()+id; //baseurl/module/action/delete/id
new Ajax.Request(delurl,{
method: 'get',
onSuccess: function(transport){
return TRUE;
}
})
}
but the problem is all foreach executes at once, and doesn't wait for response from function. It prints failed even the operation is success.
Updated
The other way round i tried first is this
jQuery('.delete-from-quote').click(function() {
var i = 0, j = 0;
jQuery(".custom-checkbox").each(function() {
if (jQuery(this).attr('data-action') == 'true') {
i++;
}
});
if (i == 0) {
alert('please choose product');
return false;
}
jQuery(".custom-checkbox").each(function() {
if (jQuery(this).attr('data-action') == 'true') {
var urlData = "<?php echo $this->getUrl('qquoteadv/index/delete/'); ?>";
urlData += "id/" + jQuery(this).attr('data-id') + "/"
var ajax = jQuery.ajax({
type: "GET",
url: urlData,
success: function(msg) {
j++;
}
})
}
if(i==j){location.reload();} //after completing all, reload the page
});
});
The problem is to know all action completed and reloading the page.
My guess is that the code you've omitted is doing an asynchronous ajax call. Since ajax is asynchronous by default, the code you write there ($.ajax or whatever) starts the process, but then the process continues in the background while your code continues to run.
There's no reasonable way to make the deleteQuoteItemFromListing function wait for the response. (While it's possible to do synchronous ajax, A) it makes for a poor user experience by locking up the browser UI, and B) jQuery will be removing that option at some stage, forcing you to go direct to XHR if you want to keep doing it.)
Instead, restructure your code to embrace the asynchronous nature of web programming by having your function either return a promise or accept a callback, and then resolve the promise or call the callback when done.
Here's a rough idea of what the promise version would look like:
jQuery(".custom-checkbox").each(function() {
if (jQuery(this).attr('data-action') == 'true') {
deleteQuoteItemFromListing(jQuery(this).attr('data-id'))
.done(function(id) {
console.log(id + ' passed');
})
.fail(function(id) {
console.log(id + ' failed');
});
}
});
function deleteQuoteItemFromListing(id){
var d = jQuery.Deferred();
jQuery.ajax(/*...*/)
.done(function() { // This bit assumes the deletion worked if
d.resolveWith(id); // the ajax call worked, and failed if the
}) // ajax call failed; if instead the ajax
.fail(function() { // call always works and returns a flag,
d.rejectWith(id); // adjust accordingly
});
return d.promise();
}
Using callback ensures that the function is executed.
jQuery(".custom-checkbox").each(function () {
if (jQuery(this).attr('data-action') == 'true') {
deleteQuoteItemFromListing(jQuery(this).attr('data-id'), handleData);
}
});
function handleData(data) {
if (data) {
console.log('passed');
} else {
console.log('failed');
}
}
function deleteQuoteItemFromListing(id, callback) {
//does someoperations and on success
delurl = getDelUrl() + id; //baseurl/module/action/delete/id
new Ajax.Request(delurl, {
method: 'get',
onSuccess: function (transport) {
callback(true);
}
})
}
I hope this will work for you. you need to define handleData function outside of the other function.
Use jquery When.
You need to queue those Deferred in an array of Deferred and then apply all of the functions at once.
If one fails all will fail and if all succeeds all will pass.
check this out jQuery When
var queue = [];
var items = 0;
return new $.Deferred(function (deferred) {
$(".custom-checkbox").each(function () {
if ($(this).attr('data-action') == 'true') {
items++;
queue.push(function () {
new Ajax.Request(delurl, {
method: 'get',
onSuccess: function (transport) {
items--;
if(items === 0)
deferred.resolve();
},
onError:function(e){
deferred.reject(e);
}
});
});
}
});
//now resolve all of the deferred fns
$.when(queue).done(function(){
console.log('All went well');
})
.fail(function(e){
console.log('Error ' + e);
});
});
(Part of) Your problem is in this simple statement:
return TRUE;
In JavaScript, the "true" boolean is written in lowercase:
return true;
The interpreter thinks TRUE is a variable, and will throw a ReferenceError, since it's not set / defined anywhere, meaning the function will never return true.

Wait until multiple functions, which may or may not call ajax internally, are complete in jQuery?

I am currently validating a few inputs clientside. When the user submits the form, I want to check the values for the form inputs, and then do something once all the checks are complete
$('form').submit(function() {
var input1 = $('form #input1');
var input2 = $('form #input2');
//validate both input values
validate_input(input1);
validate_input(input2);
//wait until all validation complete to execute code here
return false;
});
Here, the "validate_input" function will check the input value. If it passes the initial checks (such as character length), then it will make an AJAX request for further validation (ex. checking if username is taken). Something like this:
function validate_input(input){
value=input.val();
if (value.length<4){
//code to execute if input is too short
}
else {
$.ajax({
type: 'get',
url: check_input_url,
data: input.serialize(),
success: function(data){
if (data=="invalid") {
//code to execute if invalid
} else {
//code to execute if valid
}
}
});
}
}
I am currently using jQuery.when() and .done() functions, but the done() function does not wait until all the validate_input functions are completely done (including AJAX callbacks called from validate_input)
$.when(
validate_input(input1),
validate_input(input2)
).done(function(){
//code here
});
How would I wait until all the validate_input functions are complete (finished with any possible AJAX callbacks), before executing further code?
I don't see you validate_input function return anything. If you want to wait, you need to return a promise, so that you don't pass undefined to $.when():
function validate_input(input){
var value=input.val();
if (value.length<4){
return …; //code to execute if input is too short
} else {
return $.ajax({
// ^^^^^^
…
});
}
}
var inputsLength = 0, // or maybe set it to $('form input').length
inputsReady = 0;
function checkInputsValidation(){
if (++inputsReady === inputsLength) YOURSALLINPUTSAREVALIDFUNCTION();
}
function validate_input(input){
inputsLength++; // remove it if you already set inputsLength
// blablabla
$.ajax({
type: 'get',
url: check_input_url,
data: input.serialize(),
success: function(data){
if (data=="invalid") {
//code to execute if invalid
} else {
checkInputsValidation();
}
}
});
}
UPDATE: i just updated my answer. it is more likely to fit your needs now. i've added a parameter to the callback function.
use callbacks with anonymous functions and chain them:
1. add a parameter for the callback function and the callback function call:
function validate_input(input, callback){
value=input.val();
if (value.length<4){
//code to execute if input is too short
callback(false);
}
else {
$.ajax({
type: 'get',
url: check_input_url,
data: input.serialize(),
success: function(data){
if (data=="invalid") {
//code to execute if invalid
callback(false);
} else {
//code to execute if valid
callback(true);
}
}
});
}
}
2. when calling your function multiple times, chain it with anonymous functions (which are executed after success in your $.ajax-request has been fired):
$('form').submit(function() {
var input1 = $('form #input1');
var input2 = $('form #input2');
//validate both input values
validate_input(input1, function(result){
if(result == true)
{
validate_input(input2, function(result){
if(result == true)
{
//wait until all validation complete to execute code here
}
else
{
return false;
}
});
}
else
{
return false;
}
});
});

Custom validation rule with knockout.js

I'm having trouble getting a custom validation rule setup with knockout.js for checking if a username already exists. From my understanding, if the return is true then there are no errors, otherwise an error is set.
Here's an example of custom validation
//val is the username in question and searchType is the type of search(username or email)
function checkValue(val, searchType){
if(searchType == 'userName'){
$.post("/users/check_if_exists",{ 'type':'username', 'value': val },function(data) {
var info = JSON.parse(data);
if(info.username_availability == "available"){
return searchType;
//I know this is working because I've alerted the searchtype here and it displays properly
}
else{
return "unavailable";
}
});
}
}
ko.validation.rules['checkIfExists'] = {
validator: function (val, searchType) {
return searchType == checkValue(val, searchType); //if the username is availble, the searchType is returned back so it would return searchType == searchType which should be true meaning there are no errors
},
message: 'This username is taken, please select another.'
};
ko.validation.registerExtenders();
I've checked the network tab and the POST is returning the correct value. If the value is available, I return the searchType. That way, it compares searchType == searchType which should be true. However, that's not the case.
Is there any other way to accomplish what I'm trying to do?
update
Here's what I have as of now
function checkValue(val, searchType, callback) {
var callback = function(data) {
return true;
}
$.post("/users/check_if_exists", { 'type':'username', 'value': val }, function(data) {
info = JSON.parse(data);
if(info.username_availability == "available"){
callback(true);
} else {
callback(false);
}
});
}
ko.validation.rules['checkIfExists'] = {
async: true,
validator: function (val, searchType) {
alert(checkValue(val, searchType));//returns undefined
return checkValue(val, searchType);
},
message: 'This username is taken, please select another.'
};
ko.validation.registerExtenders();
ko.validation calls your validation function.
There are two types of validation functions with regards to the way they pass the success/failure state back to ko.validation: the straight-forward return true/false way, or the "async" way.
The async way exists only because $.ajax exists and it's basically just this: instead of returning a value (which is impossible, as you are using an $.ajax call) you have to somehow notify ko.validation after the ajax response gets back to the browser, right?
So the smart people who wrote this library call your validation function with an extra parameter, a function (callback), that you have to call when the response is available.
function checkValue(val, searchType, callback){
if(searchType == 'userName'){
$.post("/users/check_if_exists",{ 'type':'username', 'value': val },function(data) {
var info = JSON.parse(data);
if(info.username_availability == "available"){
callback(true);
//I know this is working because I've alerted the searchtype here and it displays properly
}
else{
callback(false);
}
});
}
}
ko.validation.rules['checkIfExists'] = {
async: true,
validator: checkValue,
message: 'This username is taken, please select another.'
};
ko.validation.registerExtenders();
Let me turn your code into something more readable:
function checkValue(val) {
var callback = function(data) {
return 'bar';
}
$.post('url', 'data', callback);
}
var x = checkValue('foo');
You are expecting x to be set to 'bar' when that is not the case.
I replaced your anonymous function with "callback" so you better understand that returning something from it does not mean "checkValue" will return anything.
After that your next problem is the fact that AJAX calls are asynchronous.
A validator function accepts three parameters: the value, extra parameters and a callback function. The callback function parameter is designed to aid you in exactly this situation.
Inside the success callback for the $.post you just have to call that callback function for the validator function passing true/false as a parameter.
function checkValue(val, params, callback) {
$.post('url', 'data', function(data) {
if(data === 'bar') {
callback(true);
} else {
callback(false);
}
});
}
checkValue as you have written it always returns undefined. Invoking "return" from inside of a callback function only sets the return value for that callback function (not the "outer function"). If the validator function expects a return value right away (as knockout appears to do) you won't be able get that data asynchronously.

assign value to global variable in javascript

I want to assign value to global variable in javascript from jquery ajax function.
var trueFalse;
$.ajax({
type: "GEt",
url: "url",
data: "text=" + $("#text").val(),
success: function(msg) {
if(msg.match(/OK/) != null) {
trueFalse = "true";
}
else {
trueFalse = "false";
}
}
});
return trueFalse;
here i need the value of trueFalse from success function.
thanks
v.srinath
Your code won't work because the line return trueFalse; executes before the success function runs, since it is called as the result of an asynchronous (as in the A in Ajax) HTTP request. You would need to pass in a callback function to this code, and invoke that in the success function:
function getWithCallback(val, callback) {
var scope = this;
$.ajax({
type: "GET",
url: "url",
data: "text=" + val,
success: function(msg) {
callback.call(scope, msg.match(/OK/) || false);
}
});
}
getWithCallback($("#text").val(), function(result) {
if (result) {
// Do something
}
});
You could try this to validate a form on submit:
var validating = false;
var valid = false;
$('#myform').submit(function(event) {
if (validating) {
return false;
}
if (valid) {
return true;
}
var form = this;
validating = true;
getWithCallback($('#text').val(), function(result) {
if (result) {
valid = true;
form.submit();
}
validating = false;
});
return false;
});
You might also want to look at the jQuery Validation plugin
If you really can't change the application logic, then you have to create a "synchronous" ajax request (by setting async:false in $.ajax options), then it will wait until the "GET" has executed and only then return the value to the caller.
Otherwise, you should rewrite the code so that the success function calls back into some callback function that it can now proceed with whatever has to be done.
Since you are doing this on form.onsubmit, you cannot do an async request. The browser won't know that it should wait until the async request is finished. The benefit of using async is that it does not lock up your scripts/browser, but in this case that is actually what you want.

Categories