I have web methods that are called via AJAX in a .Net 4.0 web app. In many cases, the AJAX calls are made repeatedly in a for loop. My problem is, the information the web method is syncing to my server is time stamped and therefore must be synced in the order in which I am sending it to AJAX. Unfortunately, it seems whatever finishes first, simply finishes first and the time stamps are all out of order. I need to basically queue up my AJAX requests so that they execute in order rather than Asynchronously, which I know is the A in AJAX so this might be a totally dumb question.
How do I force the order of execution for AJAX calls done in a for loop?
Edit: Some code
for (var i = 0; i < itemCnt - 1; i++) {
try {
key = items[i];
item = localStorage.getItem(key);
vals = item.split(",");
type = getType(key);
if (type == "Status") {
var Call = key.substring(7, 17);
var OldStat = vals[0];
var NewStat = vals[1];
var Date1 = vals[2];
var Time1 = vals[3];
var miles = vals[4];
try {
stat(Call, OldStat, NewStat, Date1, Time1, miles, key);
}
catch (e) {
alert("Status " + e);
return;
}
}
else if (type == "Notes") {
var Call = key.substring(6, 16);
var Notes = item;
try {
addNotes(Call, Notes);
}
catch (e) {
alert("Notes " + e);
return;
}
}
else if (key == "StartNCTime" || key == "EndNCTime") {
var TechID = vals[0];
var Date = vals[1];
var Time = vals[2];
var Activity = vals[3];
var Location = vals[4];
var Type = vals[5];
try {
logTime(TechID, Date, Time, Activity, Location, Type,
}
catch (e) {
alert(key + ' ' + e);
return;
}
}
}
catch (e) {
alert(key + ' ' + e);
return;
}
}
function stat(Call, OldStat, NewStat, Date1, Time1, miles, key) {
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json",
url: "Service.asmx/update_Stat",
data: '{ CallNumber:"' + Call + '", OldStat:"' + OldStat + '", NewStat:"' + NewStat + '", Date1:"' + Date1 + '", Time1:"' + Time1 + '", Miles: "' + miles + '"}',
success: function (data) { },
error: function (xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert("Sync Update Stat: " + err.Message);
location = location;
}
});
}
function logTime(TechID, Date, Time, Activity, Location, Type, key) {
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json",
url: "Service.asmx/nonCallTime",
data: '{ TechID:"' + TechID + '", Date1:"' + Date + '", Time1:"' + Time + '", Activity:"' + Activity + '", Location:"' + Location + '", Type: "' + Type + '"}',
success: function (data) { },
error: function (xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert("Sync Non Call Time: " + err.Message);
location = location;
}
});
}
function addNotes(Call, Notes) {
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json",
url: "Service.asmx/addNote",
data: '{ Call:"' + Call + '", Notes:"' + Notes + '"}',
success: function (data) { },
error: function (xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert("Sync Notes: " + err.Message);
location = location;
}
});
}
You have to use callbacks.
function ajax1(){
//..some code
//on ajax success:
ajax2();
}
//etcetera...
Or might I suggest using a javascript library like jQuery to synchronize your ajax requests for you.
set the third parameter in xmlhttp object's open method to false to make it synchronous.
http://www.w3schools.com/ajax/ajax_xmlhttprequest_send.asp
A general pattern for making actions serial would be such:
function doAjax(data, cb) {
...
// when ready call cb
}
(function (next) {
var xhr = doAjax(data, next);
})(function (next) {
var xhr = doAjax(data, next);
})(function (next) {
doAjax(data);
});
Doing so in a for loop would require recursion.
(function next() {
if ( i < n ) {
doAjax(data[i++], next);
}
})();
Related
I have 2 lists in my Sharepoint : speeches and schools.
In my speeches form, I have a school field. I want to autocomplete this field with values (name, adress, city) from schools list.
Here's my code :
$(School_fieldID).autocomplete({
minLength: 2,
source: function (request, response) {
var term = request.term.replace(/ /g, "*\",\"*");
var searchUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?querytext='and(\"*" + term + "*\",path:\"" + _spPageContextInfo.webAbsoluteUrl + "/Lists/Schools\")'&enablefql=true";
var executor = new SP.RequestExecutor(_spPageContextInfo.webAbsoluteUrl);
executor.executeAsync({
url: searchUrl,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
var jsonObject = JSON.parse(data.body);
var results = jsonObject.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results;
var clientContext = new SP.ClientContext();
var schoolList = clientContext.get_web().get_lists().getByTitle('Schools');
response($.map(results, function (result) {
school = schoolList.getItemById(result.Cells.results[6].Value.split('=').pop());
clientContext.load(school, 'Title', 'Adress', 'City');
clientContext.executeQueryAsync(Function.createDelegate(this, function (schoolName, schoolAdress, schoolCity) {
schoolName = school.get_item('Title');
schoolAdress = school.get_item('Adress');
schoolCity = school.get_item('City');
}), Function.createDelegate(this, function (sender, args) {
alert('Error occured: ' + args.get_message());
}));
return {
label: schoolName + " (" + schoolAdress + " " + /*schoolCity + */ ")",
value: schoolName
};
}));
}
});
}
});
When I test this code, schoolName, schoolAdress et schoolCity are undefined because of asynchronous function executeQueryAsync.
So I think solution is in Promise or Callback, but I tried different solutions for a week, without success :-(
Please note I read carefully this post How do I return the response from an asynchronous call?, but can't find a good solution anyway...
Can anyone help me ?
Thanks in advance,
Florent
Considering you have to pass an array of objects to the response callback function and each one of the result is calling the async function clientContext.executeQueryAsync we can turn each one of them into a promise and pass them to Promise.all() which will wait for all of them to be resolved and returned them.
When they are all resolved, the objects will be inside the schoolObjectArray which then you can pass to the response function.
Is should work.
$(School_fieldID).autocomplete({
minLength: 2,
source: function (request, response) {
var term = request.term.replace(/ /g, "*\",\"*");
var searchUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?querytext='and(\"*" + term + "*\",path:\"" + _spPageContextInfo.webAbsoluteUrl + "/Lists/Schools\")'&enablefql=true";
var executor = new SP.RequestExecutor(_spPageContextInfo.webAbsoluteUrl);
executor.executeAsync({
url: searchUrl,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
var jsonObject = JSON.parse(data.body);
var results = jsonObject.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results;
var clientContext = new SP.ClientContext();
var schoolList = clientContext.get_web().get_lists().getByTitle('Schools');
Promise.all($.map(results, function (result) {
school = schoolList.getItemById(result.Cells.results[6].Value.split('=').pop());
clientContext.load(school, 'Title', 'Adress', 'City');
return new Promise(function(resolve,reject) {
clientContext.executeQueryAsync(Function.createDelegate(this, function (schoolName, schoolAdress, schoolCity) {
schoolName = school.get_item('Title');
schoolAdress = school.get_item('Adress');
schoolCity = school.get_item('City');
resolve({
label: schoolName + " (" + schoolAdress + " " + /*schoolCity + */ ")",
value: schoolName
});
}), Function.createDelegate(this, function (sender, args) {
reject('Error occured: ' + args.get_message());
}));
})
}))
.then(function(schoolObjectArray){
response(schoolObjectArray)
})
.catch(console.error);
}
});
}
});
I am trying to post a nested json body to an api and I tried few things but couldn't work it out. Another thing is the Json values are coming from different models. It is a bit complicated and I am struggling with it, any kind of help will be appreciated.
public Object getfreight()
{
var json = "{" +
"'from': {" +
"'postcode': '3207'" +
"}," +
"'to': {" +
"'postcode': '2001'" +
"}," +
"'items': [" +
"{" +
"'length': 5," +
"'height': 5," +
"'width': 5," +
"'weight': 5," +
"'item_reference' : 'abc xyz'," +
"'features':{" +
"'TRANSIT_COVER': {" +
"'attributes': {" +
"'cover_amount':1000" +
"}" +
"}" +
"}" +
"}" +
"]" +
"}";
string url =
"https://digitalapi.auspost.com.au/postage/parcel/domestic/calculate.json?length=22&to_postcode=3083&from_postcode=3076&weight=2&height=40&width=50&service_code=AUS_PARCEL_REGULAR";
//synchronous client.
var client = new WebClient();
var serializer = new JavaScriptSerializer();
client.Credentials = new NetworkCredential("***", "***");
client.Headers.Add("Content-Type: application/json");
client.Headers.Add("Accept: application/json");
client.Headers.Add("account-number: ***");
var data = serializer.Serialize(json);
var content = client.UploadString(url,json);
var jsonContent = serializer.Deserialize<Object>(content);
return jsonContent;
}
Can't use jQuery to pass your json object to API ?
function Search () {
try {
var req = {
length:"5",
Higet: "10",
item_reference: "",
}
$.ajax({
url: https://digitalapi.auspost.com.au/postage/parcel/domestic,
type: 'POST',
data: req,
dataType: "json",
async: true,
success: function (result) {
},
error: function (e) {
}
});
}
catch (e) {
}
}
Can anyone help me with this code? I would like to convert this async ajax to sync ajax. How do I do it? Here is the code that is written below. The system just lags when I leave it for 20 mins without even doing anything. So, maybe the problem is within the code.
function addmsg20(type, msg, data) {
$('#display20').html(data);
}
function waitForMsg20() {
$.ajax({
type: "GET",
url: "liprintednotif.php",
async: true,
cache: false,
timeout: 50000,
success: function(data) {
var data = JSON.parse(data);
if(data.data.length > 0){
var res = data.data;
var printed = "<ul class='menu'>";
$.each(res, function(k, v){
var empext = v.employee_ext;
if(empext == null){
empext = "";
}else{
empext = v.employee_ext;
}
printed += "<li>" +
"<a href='#'>" +
"<h4>" +
" "+v.employee_fname + " " +
v.employee_mname+" "+v.employee_lname+" " +empext+ "<small>" +
v.status_desc+ "</small>" +"</h4>" +
"<p>" + v.subj_name + "</p>" +
"</a></li>";
})
printed += "</ul>";
}else{
printed = "";
}
addmsg20("new", data.count, printed);
setTimeout(
waitForMsg20,
1000);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
addmsg20("error", textStatus + " (" + errorThrown + ")");
setTimeout(
waitForMsg20,
15000);
}
});
};
$(document).ready(function() {
waitForMsg20();
});
I am completely new to Javascript and/or AJAX so I really need help about this.
To make the AJAX call synchronous, just set async to false:
$.ajax({
type: "GET",
url: "liprintednotif.php",
async: false,
cache: false,
timeout: 50000,
.
.
.
I am trying to detect wither a database entry has been successfully input by sending the new inserted ID and a JSON variable to an AJAX call but it is not working in phonegAP, however it is fine in all browsers and I can see that the data is being inserted in the db successfully. All comments/ help appreciated, thanks.
AJAX code -
function InsertQnA() {
$.ajax({
url: Domain + '/Result/Create',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: '{"Q1":"' + Q1 + '","Q2":"' + Q2 + '","Q3":"' + Q3 + '","Q4":"' + Q4 + '","Q5":"' + Q5 + '","Q6":"' + Q6 + '","Q7":"' + Q7 + '","Q8":"' + Q8 + '","Q9":"' + Q9 + '","Q10":"' + Q10 + '","Total":"' + localStorage.getItem("Total", Total) + '","CaseStudy":"' + localStorage.getItem("CaseStudy") + '","UserId":"' + localStorage.getItem("UserId") + '","Attempts":"' + QnANumAttempts + '"}',
success: function (data) {
alert('this alert is invoked successfully');
if (data.Success == true) {
alert('this alert is not being invoked successfully');
//result id used for feedback insertion > update result entity
localStorage.setItem("ResultId", data.ResultId);
viewModel.UserId("You have successfully completed case study " + localStorage.getItem("CaseStudy") + ", please fill out the <a href='evaluation.html' target='_self'>evaluation.</a>");
}
else if (data.Success==false)
{
alert('this alert is not being invoked either');
viewModel.UserId("Your entry has not been saved, please try again.");
}
},
}).fail(
function (xhr, textStatus, err) {
console.log(xhr.statusText);
console.log(textStatus);
console.log(err);
});
}
mvc function
//
// POST: /Result/Create
[HttpPost]
public ActionResult Create(Result result)
{
if (ModelState.IsValid)
{
result.ResultDate = DateTime.Now;
repository.InsertResult(result);
repository.Save();
if (Request.IsAjaxRequest())
{
int ResultId = result.ResultId;
try
{ //valid database entry..send back new ResultId
return Json(new { Success = true, ResultId, JsonRequestBehavior.AllowGet });
}
catch
{ // no database entry
return Json(new { Success = false, Message = "Error", JsonRequestBehavior.AllowGet });
}
}
return RedirectToAction("Index");
}
return View(result);
}
Found two issues with the code:
1.localStorage.getItem("Total", Total) should be localStorage.getItem("Total")
2.dataType : "json" not explicitly mentioned.
I have posted with the relevant corrections.Try this if it helps and also share if if you get any errors.
function InsertQnA() {
$.ajax({
url: Domain + '/Result/Create',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: '{"Q1":"' + Q1 + '","Q2":"' + Q2 + '","Q3":"' + Q3 + '","Q4":"' + Q4 + '","Q5":"' + Q5 + '","Q6":"' + Q6 + '","Q7":"' + Q7 + '","Q8":"' + Q8 + '","Q9":"' + Q9 + '","Q10":"' + Q10 + '","Total":"' + localStorage.getItem("Total") + '","CaseStudy":"' + localStorage.getItem("CaseStudy") + '","UserId":"' + localStorage.getItem("UserId") + '","Attempts":"' + QnANumAttempts + '"}',
dataType : "json",
success: function (data) {
alert('this alert is invoked successfully');
try {
if (data.Success == true) {
alert('this alert is not being invoked successfully');
//result id used for feedback insertion > update result entity
localStorage.setItem("ResultId", data.ResultId);
viewModel.UserId("You have successfully completed case study " + localStorage.getItem("CaseStudy") + ", please fill out the <a href='evaluation.html' target='_self'>evaluation.</a>");
}
else if (data.Success==false)
{
alert('this alert is not being invoked either');
viewModel.UserId("Your entry has not been saved, please try again.");
}
}catch(error) {
alert("This is the error which might be: "+error.message);
}
},
}).fail(
function (xhr, textStatus, err) {
console.log(xhr.statusText);
console.log(textStatus);
console.log(err);
});
}
Make these changes in your server side code.
var json = "";
try
{ //valid database entry..send back new ResultId
json = Json.Encode(new { Success = true, ResultId, JsonRequestBehavior.AllowGet });
}
catch
{ // no database entry
json = Json.Encode(new { Success = false, Message = "Error", JsonRequestBehavior.AllowGet });
}
Response.Write(json);
From what I have gathered (over the past two days) an MVC ActionResult does not seem to easily serve a webapp with data. I got round this by duplicating the ActionResult with a string method and it works fine now. Probably not the best solution but I have heard that its better to create two action methods instead of having one when serving a web view and a web app. Many thanks to everyone who posted.
MVC Action -
[HttpPost]
public string CreateResult(Result result)
{
result.ResultDate = DateTime.Now;
repository.InsertResult(result);
repository.Save();
if (result == null)
{
// User entity does not exist in db, return 0
return JsonConvert.SerializeObject(0);
}
else
{
// Success return user
return JsonConvert.SerializeObject(result, Formatting.Indented, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
}
}
AJAX -
$.ajax({
url: Domain + '/Result/CreateResult',
cache: false,
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: '{"Q1":"' + Q1 + '","Q2":"' + Q2 + '","Q3":"' + Q3 + '","Q4":"' + Q4 + '","Q5":"' + Q5 + '","Q6":"' + Q6 + '","Q7":"' + Q7 + '","Q8":"' + Q8 + '","Q9":"' + Q9 + '","Q10":"' + Q10 + '","Total":"' + localStorage.getItem("Total") + '","CaseStudy":"' + localStorage.getItem("CaseStudy") + '","UserId":"' + localStorage.getItem("UserId") + '","Attempts":"' + QnANumAttempts + '"}',
success: function (data) {
try {
if (data != 0) {
//result id used for feedback insertion > update result entity
localStorage.setItem("ResultId", data.ResultId);
viewModel.UserId("You have successfully completed case study " + localStorage.getItem("CaseStudy") + ", please fill out the <a href=evaluation.html target=_self>evaluation.<a/>");
//reset locals
ResetLocalStorage();
//count number of entities for User
CountUserEntitiesInResults();
}
else
{
viewModel.UserId("Your entry has not been saved, please try again.");
}
}catch(error) {
alert("This is the error which might be: "+error.message);
}
},
}).fail(
function (xhr, textStatus, err) {
console.log(xhr.statusText);
console.log(textStatus);
console.log(err);
});
here is my example
var url = "http://maps.googleapis.com/maps/api/geocode/json?latlng=" + area.getCenter().lat + "," + area.getCenter().lng + "&sensor=false";
$.getJSON(url, function (data) {
alert("inside json");
//console.log(data);
$.each(data.results[0], function (i, inside) {
console.log(i);
});
//var addr = data.results[0].geometry.location.lat;
});
now i realized that the call function doesn't fire at all....i read other post here and they say that it happens when JSON is not in valid format but here i am getting JSON from Google API so i hope its in valid format.... JSON is here
http://maps.googleapis.com/maps/api/geocode/json?latlng=27.88,78.08&sensor=false
can you please give your comments on this? or may be i am making some mistakes
Maybe try a full ajax call:
$.ajax({
url: "http://maps.googleapis.com/maps/api/geocode/json?latlng=" + area.getCenter().lat + "," + area.getCenter().lng + "&sensor=false",
data: {},
type: "GET",
contentType: "application/json; charset=utf-8",
dataType: "JSON",
timeout: 10000,
success: function (Result) {
for (var i = 0; i < Result.d.length; i++) {
element = Result.d[i];
console.log(element);
};
},
error: function (xhr, status) {
alert(status + " - " + xhr.responseText);
}
});
can you add it to
$(document).ready(function(){
});
for example:
$(document).ready(function () {
var url = "http://maps.googleapis.com/maps/api/geocode/json?latlng=" + area.getCenter().lat + "," + area.getCenter().lng + "&sensor=false";
$.getJSON(url, function (data) {
alert("inside json");
//console.log(data);
$.each(data.results[0], function (i, inside) {
console.log(i);
});
//var addr = data.results[0].geometry.location.lat;
});
});