I have a function to add a record to database that uses Ajax with C# web service. Prior to updating DB I call another function to validate input that also uses Ajax. So, I need the validate function to finish before continuing with the one adding the record.
I know due to asynchronous nature of ajax I have to use promise/deferred but just can't get my head wrapped around it to set it up properly.
Updated
function validate() {
var deferred = $.Deferred();
$.ajax({
url: "path/to/web/service",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: params,
}).done(function (result) {debugger
if (!result || result.d === "") {
isValid = false;
}
else {
var duplicate = JSON.parse(result.d);
switch (duplicate) {
case DuplicateData.Name:
isValid = false;
break;
case DuplicateData.ID:
isValid = false;
break;
}
}
}).fail(function (jqXHR, textStatus, errorThrown) {
alert(textStatus + ' - ' + errorThrown + '\n' + jqXHR.responseText);
});
deferred.resolve(isValid);
return deferred.promise();
//return isValid;
}
$(document).on("click", "#btnAdd", function (event) {debugger
$.when(validate())
.then(function(isValid) {
if (isValid) {
$.ajax({
url: "path/to/another/webservice",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: some_param,
}).done(function (result) {
addNewRecord();
)}.fail(function (jqXHR, textStatus, errorThrown) {
alert(textStatus + ' - ' + errorThrown + '\n' + jqXHR.responseText);
});
}
})
});
function addNewRecord(){
// add record to DB
}
As you are only dealing with a boolean result, there is no reason to return a value, you can just resolve or reject the deferred.
function validate() {
var $defer = $.Deferred(function() {
$.ajax({
url: "path/to/web/service",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: params,
})
.done(function (result) {
// If there's no result
if (!result || !result.d) {
$defer.reject();
}
else {
// This call shouldn't be necessary, as dataType: "json" will call it for you
// Unless you double-encoded it.
var duplicate = JSON.parse(result.d);
// Not sure about this part, what's DuplicatedData and what does result.d contain?
switch (duplicate) {
case DuplicateData.Name:
case DuplicateData.ID:
$defer.reject();
}
}
// Everything checks out, resolve the promise
$defer.resolve();
})
.fail(function (jqXHR, textStatus, errorThrown) {
// If there was a network or server error
// alert(textStatus + ' - ' + errorThrown + '\n' + jqXHR.responseText);
$defer.reject();
});
});
return $defer;
}
$('form').on("click", "#btnAdd", function (event) {
validate()
.done(function() {
// If the validation passes
$.ajax({
url: "path/to/another/webservice",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: some_param,
})
.done(function (result) {
// Creation successful
addNewRecord();
}).fail(function (jqXHR, textStatus, errorThrown) {
// Creation failed
alert(textStatus + ' - ' + errorThrown + '\n' + jqXHR.responseText);
});
})
.fail(function(reason) {
// Called in case of a validation error
console.log("Validation error");
});
});
Related
Here is a getData method and I am unable to get row using multiple conditions.
because I am trying to set input value where rows condition is matched. but it's not working yet
function getData() {
$.ajax({
type: 'POST',
url: APIUrl + 'api/GetCustomerProductDetailsDetailByEmployeeID?JSONStringData=' + JSON.stringify(objReqCustomerProductDetails),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
crossDomain: true,
success: function (data, textStatus, xhr) {
objResCustomerProductDetails = data;
if ($(objResCustomerProductDetails.CustomerProductDetails).length > 0) {
$.each(objResCustomerProductDetails.CustomerProductDetails, function () {
$('#tbCustomer tbody tr[data-id=' + this.CustomerID + ' data-product-id=' + this.ProductID + '] td').find('input').val(parseFloat(this.Quantity.toString().trim()).toFixed(2));
});
}
},
error: function (xhr, textStatus, errorThrown) {
messageProvider(0, errorThrown);
}
});
}
$('#tbCustomer tbody tr[data-id=' + this.CustomerID + '][data-product-id=' + this.ProductID + '] td').find('input').val(parseFloat(this.Quantity.toString().trim()).toFixed(2));
After an attribute ends you need to close it. Convention is [attr1][attr2]. This was the problem with the above code.
Ref: https://api.jquery.com/multiple-attribute-selector/
I have a method that sends AJAX request and returns a result that indicates a JSON string of Tokens records, I'm trying to get this result and assign it to a global variable called tokens and then reuse this global variable in other functions.
I'm assigning the result to that variable and log it to the console as follows:
var tokens = null;
function PopulateAllTokens() {
$.ajax({
type: "POST",
url: "NewToken.aspx/PopulateAllTokens",
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Request: " + JSON.stringify(XMLHttpRequest) + "\n\nStatus: " + textStatus + "\n\nError: " + errorThrown);
},
success: function (result) {
tokens = JSON.parse(result.d);
console.log(tokens);
populateTokensToTable(tokens);
}
});
}
The issue is that, when I assign the result to the variable and then log it to the console it shows the result successfully, but when I want to reuse it later in other functions it shows that the variable is still null.
For example I want to use it in the following jQuery code but it shows that the variable is null:
$("#example").DataTable({
"columns": getTokens(),
"data": tokens
});
Just to clarify that both variable and function are being defined inside:
$(document).ready(function () {//function and var}
Any suggestions please?
Make sure the AJAX callback has finished before using the variables globally
Most of the time problems arise when you try to get a value via AJAX and then try to use that value outside the whole $.ajax() construct. The reason is that responses from async calls can only be accessed safely inside their success or complete callbacks - there is no guarantee the value will be populated before either of those callbacks complete. To work around this, you can either move all following code to be called from inside the AJAX callback, or wait for your global vars to be set by the callback.
Using the callback to continue running your script
var tokens = null;
function PopulateAllTokens() {
$.ajax({
type: "POST",
url: "NewToken.aspx/PopulateAllTokens",
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Request: " + JSON.stringify(XMLHttpRequest) + "\n\nStatus: " + textStatus + "\n\nError: " + errorThrown);
},
success: function (result) {
tokens = JSON.parse(result.d);
console.log(tokens);
populateTokensToTable(tokens);
EverythingElseYouWantToRun();
}
});
}
function EverythingElseYouWantToRun() {
// you can do whatever you want with the response here
$("#example").DataTable({
"columns": getTokens(),
"data": tokens
});
}
Await the variable with your consuming script
var tokens = null;
function PopulateAllTokens() {
$.ajax({
type: "POST",
url: "NewToken.aspx/PopulateAllTokens",
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Request: " + JSON.stringify(XMLHttpRequest) + "\n\nStatus: " + textStatus + "\n\nError: " + errorThrown);
},
success: function (result) {
tokens = JSON.parse(result.d);
console.log(tokens);
populateTokensToTable(tokens);
}
});
}
function RunWhenVariableIsPopulated(variable, callback, timeout) {
if (variable === null) {
setTimeout(function() {
RunWhenVariableIsPopulated(variable, callback, timeout);
}, timeout);
} else {
callback(variable);
}
}
Then later you can call:
RunWhenVariableIsPopulated(tokens, function() {
$("#example").DataTable({
"columns": getTokens(),
"data": tokens
});
}, 400 /* or whatever your average round-trip time is*/);
Beware: this can cause the browser to hang noticeably if your AJAX response time is really long, and effectively turns an async call into a synchronous one. Hope this helps with your current situation!
function getData(){
return $.ajax({
type: "POST",
url: "NewToken.aspx/PopulateAllTokens",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: false,
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Request: " + JSON.stringify(XMLHttpRequest) + "\n\nStatus: " + textStatus + "\n\nError: " + errorThrown);
},
success: function (result) {
tokens = JSON.parse(result.d);
console.log(tokens);
populateTokensToTable(tokens);
}
}).responseText;
}
var res = getData();
Above code will store the response in the variable and after that you can parse it and modify as you need. I am not sure, but It may help you
use $.parseJSON() Method
$(document).ready() is doesn't matter, only thing is functions calls flow, you can declare the function outside also and call it accordingly, and also its good to check the variable null or not like
var tokens = null;
function PopulateAllTokens() {
$.ajax({
type: "POST",
url: "NewToken.aspx/PopulateAllTokens",
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Request: " + JSON.stringify(XMLHttpRequest) + "\n\nStatus: " + textStatus + "\n\nError: " + errorThrown);
},
success: function (result) {
tokens = $.parseJSON(result.d);
console.log(tokens);
populateTokensToTable(tokens);
}
});
}
if(tokens)
console.log(tokens);
I have a field on my database that stores a number of clicks, and want to increment that when I click in a link(<a href="#selecoes" data-identity="31" id="clicks" clicks="0">) of my tag cloud. Note that I get the number of clicks throught my webservice. This is I do so far:
index.html
<div id="tags">
<ul id="tagList">
<li>
<img src='.../>Brasil
</li>
</ul>
main.js
$('#tagList a').live('click', function() {
findByIdSelecoes($(this).data('identity'));
});
function findByIdSelecoes(id) {
console.log('findByIdSelecoes: ' + id);
$.ajax({
type: 'GET',
url: rootURLSelecoes + '/id/' + id,
dataType: "json",
success: function(data){
$('#btnDelete').show();
console.log('findByIdSelecoes success: ' + data.nome);
currentWine = data;
renderDetails(currentWine);
findJogadoresBySelecao(id);
addClick(currentWine);
}
});
}
function addClick(selecao) {
console.log('addClick na seleção: ' + selecao.id_selecao);
$.ajax({
type: 'PUT',
contentType: 'application/json',
url: rootURLSelecoes + '/update/' + selecao.id_selecao,
dataType: "json",
data: formToJSON(),
success: function(data, textStatus, jqXHR){
alert('clicks updated successfully');
},
error: function(jqXHR, textStatus, errorThrown){
alert('updateWine error: ' + textStatus);
}
});
}
function formToJSON() {
return JSON.stringify({
"clicks": ($('#clicks').val())++ // i dont know what i have to do so i try this(don't work)
});
}
I can't update the dataBase when I click the link in the list. The function formToJSON doesn't increment the value in the database.
Try to do this
Make a var number like global, and do this:
function addClick(selecao) {
console.log('addClick na seleção: ' + selecao.id_selecao);
number = parseInt(selecao.clicks,10);
$.ajax({
type: 'PUT',
contentType: 'application/json',
url: rootURLSelecoes + '/update/' + selecao.id_selecao,
dataType: "json",
data: formToJSON(),
success: function(data, textStatus, jqXHR){
alert("Done: " +number);
},
error: function(jqXHR, textStatus, errorThrown){
alert('updateWine error: ' + textStatus);
}
});
}
function`enter code here` formToJSON() {
var ola = parseInt(number,10);
ola = ola +1;
return JSON.stringify({
"clicks": parseInt(ola,10)
});
}
I have a page, and i've got a link looking like:
<span>Nordjylland</span>
And in my Javascript file, i've got a function called GetCitiesByRegion(), however, when clicking the link, i get an error, saying that GetCitiesByRegion is not defined?
The function looks like this:
function GetCitiesByRegion(id) {
var params = '{"id":"' + id + '"}'
var request = {
type: "GET",
async: false,
cache: false,
url: "http://" + location.hostname + "/webservices/services.svc/GetCitiesByRegion",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: params,
success: function (result) {
alert("Data Loaded: " + result);
},
error: function (xhr, status, error) {
alert('Fejl ved webservice: error: ' + error);
}
};
$jq.ajax(request);
}
I have a javascript function which makes a JSON call to a web service using jQuery.
In the success function I need to evaluate the JSON response and if necessary make another call to a different method in the same web service.
Here is how I do it:
function firstAjaxCall(aid, tid) {
$.ajax({
type: "POST",
contentType: "application/json;charset=utf-8",
url: "/webservices/Webservice.asmx/Method1",
data: "{ auctionId: '" + aid + "'}",
dataType: "json",
success: function (response) {
var respData = response.d;
//do some stuff
if (respData.HasEnded == true) {
clearInterval(tid);
var end = false;
end = endFunction(aid);
if (end) {
// do some other stuff
}
}
},
failure: function (errorMsg) { alert(errorMsg.toString()); }
});
}
and the endFunction which is being called from within the ajax success function:
function endFunction(aid) {
var hasEnded = false;
$.ajax({
type: "POST",
contentType: "application/json;charset=utf-8",
url: "/webservices/Webservice.asmx/Method2",
data: "{ auctionId: '" + aid + "'}",
dataType: "json",
success: function (callbackData) {
var endRespData = callbackData.d;
hasEnded = endRespData.Success;
alert(hasEnded.toString());
},
failure: function(XMLHttpRequest, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
}
});
return hasEnded;
}
Here is the weird stuff. The ajax-call is made all right. The code on the server is running according to plan. However, if I try to set a firebug breakpoint in the success function of endFunction(aid) is is not hit, but the alert box is shown displaying the word true. This is somewhat good since it seems that we are actually reaching the success function. The hasEnded variable however is never set to true so it always returns false.
Calling endFunction(1) from the Firebug console displays an alert box with the word true and returns value false.
What's going wrong?
AJAX is asynchronous — the $.ajax call will not wait for the server to reply.
Therefore, the return hasEnded; line runs before the AJAX callback.
You need to make your endFunction take a callback parameter, like $.ajax does.
http://api.jquery.com/jQuery.ajax/
It looks like you're using "failure" in the documentation you have "error":
error(XMLHttpRequest, textStatus, errorThrown)
also you should do something like this:
function firstAjaxCall(aid, tid) {
$.ajax({
type: "POST",
contentType: "application/json;charset=utf-8",
url: "/webservices/Webservice.asmx/Method1",
data: "{ auctionId: '" + aid + "'}",
dataType: "json",
success: function (response) {
var respData = response.d;
//do some stuff
if (respData.HasEnded == true) {
clearInterval(tid);
var end = false;
endFunction(aid,function(endv){
if (endv) {
// do some other stuff
}
});
}
},
error: function (errorMsg) { alert(errorMsg.toString()); }
});
}
function endFunction(aid,endcallback) {
var hasEnded = false;
$.ajax({
type: "POST",
contentType: "application/json;charset=utf-8",
url: "/webservices/Webservice.asmx/Method2",
data: "{ auctionId: '" + aid + "'}",
dataType: "json",
success: function (callbackData) {
var endRespData = callbackData.d;
hasEnded = endRespData.Success;
alert(hasEnded.toString());
endcallback(hasEnded);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
endcallback("?");
}
});
//return hasEnded;
}