I call a sync web services in my web site but there is no waiting of thier results.
I'm caling the function loadExtLayout in the function loadLayout , after that I'm calling the function loadLayout in other functions in the web site
HTTPRequestService.prototype.loadExtLayout = function(pathToLoad){
logManager.IHM_LOG_INFO("BEGIN HTTPRequestService loadExtLayout call pathToLoad="+JSON.stringify(pathToLoad));
var loadResult = null;
$.ajax({
async:false,
method: "GET",
url: pathToLoad
}).done(function(result){
loadResult = result;
}).fail(function(jqXHR, textStatus){
loadResult = null;
logManager.IHM_LOG_ERROR(new Error().stack+": "+"Error loading layout : " + pathToLoad + " (" + textStatus + ")\n");
});
logManager.IHM_LOG_INFO("END HTTPRequestService loadExtLayout call");
return loadResult;
}
GenericLayoutController.prototype.loadLayout = function(layoutName){
logManager.IHM_LOG_INFO("BEGIN loadLayout");
var loadResult = false;
var layoutContent = null;
try {
var httpService = new HTTPRequestService(this.AppId);
if(httpService != null){
layoutContent = httpService.loadExtLayout(layoutName);
console.log("layoutContent :" + layoutContent);
if ((layoutContent != null) && ($("#window_"+ this.AppId + "_" + this.WndId).attr("patternname") == this.patternName)) {
$("#window_"+ this.AppId + "_" + this.WndId).empty();
$("#window_"+ this.AppId + "_" + this.WndId).html(layoutContent);
loadResult = true;
} else if( layoutContent == null ){
logManager.IHM_LOG_ERROR("Error loading layout !");
}
} else {
logManager.IHM_LOG_ERROR("Error unable to create HTTPRequestService object : httpService is null !");
}
} catch(e) {
loadResult = false;
logManager.IHM_LOG_ERROR(new Error().stack+": "+e+"\n");
}
logManager.IHM_LOG_INFO("END loadLayout");
return loadResult;
}
if you using ajax param 'async: false', you gotta use callback(success) instead of promises, cause 'then' work asynchronously and 'return' executing before promise retriev data from server.
let data = null;
$.ajax({
async:false,
method: "GET",
url: pathToLoad,
success:(response)=>{data = response}
});
return data;
or you can do it asynchronously
HTTPRequestService.prototype.loadExtLayout = function(pathToLoad){
logManager.IHM_LOG_INFO("BEGIN HTTPRequestService loadExtLayout call pathToLoad="+JSON.stringify(pathToLoad));
let loadResult = new Promise((resolve,reject)=>{
$.ajax({
async:false,
method: "GET",
url: pathToLoad
}).done(function(result){
resolve(result);
}).fail(function(jqXHR, textStatus){
reject(textStatus);
loadResult = null;
logManager.IHM_LOG_ERROR(new Error().stack+": "+"Error loading layout : " + pathToLoad + " (" + textStatus + ")\n");
});
});
logManager.IHM_LOG_INFO("END HTTPRequestService loadExtLayout call");
return loadResult;
}
Related
I'm performing two separate AJAX calls and I'd ultimately like for the results to be in the form of a number variable that I can manipulate. I've wrapped the execution of the functions within $(function() in an attempt to wait until both of the AJAX functions have returned their value so as not to begin to do the math before the results are returned, but it appears that's not working.
How can I ensure that the results are returned from two separate AJAX calls before the function manipulates their results?
// Collect Data Point P
function myCallbackP(result) {
var p = Math.round(result/3);
$('#past').html(p);
}
fooP(myCallbackP);
function fooP (callback){
$.ajax({
url: 'https://' + company + '.teamwork.com/' + actionP,
headers: {"Authorization": "BASIC " + window.btoa(key)},
}).done(function(response){
callback((response['todo-items']).length);
})
}
//Collect Data Point F
function myCallbackF(result) {
var f = (result);
$('#future').html(f);
}
fooF(myCallbackF);
function fooF (callback){
$.ajax({
url: 'https://' + company + '.teamwork.com/' + actionF,
headers: {"Authorization": "BASIC " + window.btoa(key)},
}).done(function(response){
callback((response['todo-items']).length);
})
}
//Math up data point P and F
$(function() {
var v = myCallbackP();
var y =myCallbackP;
var z = v/y;
console.log(z);
$('#ratio').html(z);
console.log('success?');
console.log( "ready!" );
});
You can use $.when()
// Collect Data Point P
function myCallbackP(result) {
var p = Math.round(result / 3);
$('#past').html(p);
}
function fooP(callback) {
return $.ajax({
url: 'https://' + company + '.teamwork.com/' + actionP,
headers: {
"Authorization": "BASIC " + window.btoa(key)
}
})
}
//Collect Data Point F
function myCallbackF(result) {
var f = (result);
$('#future').html(f);
}
function fooF(callback) {
return $.ajax({
url: 'https://' + company + '.teamwork.com/' + actionF,
headers: {
"Authorization": "BASIC " + window.btoa(key)
}
})
}
//Math up data point P and F
$(function() {
$.when(fooP(), fooF())
.then(function(p, f) {
console.log('success?');
myCallbackP(p[0]["todo-items"].length);
myCallbackF(f[0]["todo-items"].length);
var v = +$("#past").html();
var y = +$("#future").html();
var z = v / y;
console.log(z);
$('#ratio').html(z);
})
.fail(function(jqxhr, textStatus, errorThrown) {
console.log(errorThrown);
});
console.log("ready!");
});
I suggest you use jQuery Deferred and Promises like below
var ajax1 = fooP();
function fooP() {
var defObj = $.Deferred();
$.ajax({
url: 'https://' + company + '.teamwork.com/' + actionP,
headers: {
"Authorization": "BASIC " + window.btoa(key)
},
}).done(function(response) {
defObj.resolve(response);
});
return defObj.promise();
}
var ajax2 = fooF();
function fooF() {
var defObj = $.Deferred();
$.ajax({
url: 'https://' + company + '.teamwork.com/' + actionF,
headers: {
"Authorization": "BASIC " + window.btoa(key)
},
}).done(function(response) {
defObj.resolve(response);
});
return defObj.promise();
}
// when both calls are done
$.when(ajax1, ajax2).done(function(data1, data2) {
var p = Math.round(data1 / 3);
$('#past').html(p);
var f = (data2);
$('#future').html(f);
var z = p / f;
console.log(z);
$('#ratio').html(z);
console.log('success?');
console.log("ready!");
});
I have a simple series of functions :
convertXML();
function convertXML(){
var xmlObj = xmlToJson(xml.responseXML)
.query.results.WMS_Capabilities;
console.log("convertXML");
(function checkReturn(){
if(typeof xmlObj != 'undefined'){
return (function(){ return createData(xmlObj)})();
}
else {
setTimeout(checkReturn, 50);
}
})();
}
function createData(xmlObj){
for (var i = 0; i < xmlObj.Capability.Layer.Layer.length; i++){
var row={};
row = xmlObj.Capability.Layer.Layer[i];
WMSLayers.push(row);
};
console.log("createdata",WMSLayers)
return (function(){return finish()})();
}
function finish(){
console.log(n == Server.length-1)
if (n == Server.length-1){
//n is defined as an argument
//this code is a part of a bigger function
//same for Server variable
createTable();
};
}
The problem is that that the convertXML function sometimes returns the callback function createData with the xmlObj variable undefined. So I have to check if the variable is defined to call the callback function.
My question is isn't a function suppose to return when all its variables are finished loading data?
UPDATE
This is how I make the request:
var req = {
"type" :"GET",
"dataType":"XML",
"data" : null,
"url" : url
};
//make the request (ajax.js)
ajax(req,ajaxSuccess,ajaxError);
function ajax(prop,onsuccess,onerror){
// data = data || null;
// var url = "wps"; // the script where you handle the form input.
$.ajax({
type: prop.type,
dataType: prop.dataType,
data: prop.data,
url: prop.url,
success: function (data, textStatus, xhr) {
console.log(xhr)
onsuccess(xhr);
},
error:function (data ,textStatus, xhr) {
onerror(xhr);
}
});
// e.preventDefault();
}
function ajaxSuccess(xhr){
$("#messages").append(
'<span style="color:blue">' +
getFullTime() +
'</span> Response HTTP status <b>' +
xhr.status +
' [' + xhr.statusText + ']' +
'</b> from:' +
' <a style="color:grey;text-decoration:none;" href="' +
url+
'" target="_blank">'+
Server[i].link +
Request["getCapabilities"]+
'</a><br>'
);
//create the wms
createWMS(xhr, Server[i],i);//this is where the convertXML,createData and finish functions are located
};
You can use the complete function of $.get(). Note, n does not appear to be defined within finish function.
function convertXML(xml, textStatus, jqxhr) {
var xmlObj = xmlToJson(jqxhr.responseXML)
.query.results.WMS_Capabilities;
console.log("convertXML");
if (typeof xmlObj != 'undefined') {
createData(xmlObj);
}
}
function createData(xmlObj){
for (var i = 0; i < xmlObj.Capability.Layer.Layer.length; i++){
var row = xmlObj.Capability.Layer.Layer[i];
WMSLayers.push(row);
};
console.log("createdata",WMSLayers)
finish();
}
$.get("/path/to/resource", convertXML, "xml")
.fail(function(jqxhr, textStatus, errorThrown) {
console.log(errorThrown)
});
I am not sure if this is due to the fact that getJSON is asynchronous or not. I think that would be the most obvious reason, but I don't have a clear understanding of how that works. In my js file, I call the healthCheck method on the body element. Nothing happens. Is my getJSON callback function even getting called? I don't know.
I have uploaded the script on JSFiddle.
The code is also below:
var baseURL = "http://someURL";
var id = "00000001";
var key = "0000aaaa-aa00-00a0-a00a-0000000a0000";
var healthcheck = "/version/healthcheck?";
( function($) {
$.fn.healthCheck = function() {
var timestamp = new Date().toJSON().toString();
var request = healthcheck + "timestamp=" + timestamp + "&devid=" + id;
var signature = CryptoJS.HmacSHA1(request, key);
request = baseURL + request + "&signature=" + signature;
$.getJSON(request, function(data) {
var result = new Object();
$.each(data, function(key, val) {
result.key = val;
if (val == false) {
this.innerHTML = "PTV API is currently not working. Error type: " + key + ".";
} else {
this.append(key + " working. <br />");
}
});
});
return this;
};
}(jQuery));
Many thanks in advance. I hope my query is well placed. If anyone knows some good resources to get a better understanding of asynchronous methods in jQuery that would be greatly appreciated, also. I haven't found many that have been easy to follow yet.
Try 1) setting context of jQuery.ajax( url [, settings ] ) to this of $.fn.healthCheck ; 2) create reference to this object at $.each()
var baseURL = "http://someURL";
var id = "00000001";
var key = "0000aaaa-aa00-00a0-a00a-0000000a0000";
var healthcheck = "/version/healthcheck?";
(function($) {
$.fn.healthCheck = function() {
// set `this` object within `$.getJSON`
var timestamp = new Date().toJSON().toString();
var request = healthcheck + "timestamp=" + timestamp + "&devid=" + id;
var signature = CryptoJS.HmacSHA1(request, key);
request = baseURL + request + "&signature=" + signature;
$.ajax({
url:request
, type:"GET"
, contentType: false
, context: this
, processData:false
}).then(function(data) {
// reference to `this` within `$.each()`
var that = this;
var result = new Object();
$.each(JSON.parse(data), function(key, val) {
result.key = val;
if (val == false) {
// `that` : `this`
that.innerHTML = "PTV API is currently not working. Error type: " + key + ".";
} else {
that.append(key + " working. <br />");
console.log("complete"); // notification
}
});
}, function(jqxhr, textStatus, errorThrown) {
console.log(textStatus, errorThrown); // log errors
});
return this;
};
}(jQuery));
$("body").healthCheck();
See also How do I return the response from an asynchronous call?
var baseURL = "https://gist.githubusercontent.com/guest271314/23e61e522a14d45a35e1/raw/62775b7420f8df6b3d83244270d26495e40a1e9d/a.json";
var id = "00000001";
var key = "0000aaaa-aa00-00a0-a00a-0000000a0000";
var healthcheck = "/version/healthcheck?";
(function($) {
$.fn.healthCheck = function() {
var timestamp = new Date().toJSON().toString();
var request = healthcheck + "timestamp=" + timestamp + "&devid=" + id;
var signature = 123;// CryptoJS.HmacSHA1(request, key);
request = baseURL + request + "&signature=" + signature;
$.ajax({
url:request
, type:"GET"
, contentType: false
, context: this
, processData:false
}).then(function(data) {
var that = this;
var result = new Object();
$.each(JSON.parse(data), function(key, val) {
result.key = val;
if (val == false) {
that.innerHTML = "PTV API is currently not working. Error type: " + key + ".";
} else {
that.append(key + " working. <br />");
console.log("complete"); // notification
}
});
}, function(jqxhr, textStatus, errorThrown) {
console.log(textStatus, errorThrown); // log errors
});
return this;
};
}(jQuery));
$("body").healthCheck()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
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);
});
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);
}
})();