This is something that should be dead easy, but I can't figure it out for the life of me, and can't find anything online to really help me.
I have a list ['flower', 'grass', 'rock', 'sand']. I need to perform 4 corresponding POST queries with the form "/myapi/flower" and json data as POST. I then want to put the results into a list or whatever to use later at my leisure.
When I go synchronous, everything works well but of course this freezes up the UI.
$(document).ready(function() {
//hang on event of form with id=myform
$("#submitCall").click(function(e) {
//prevent Default functionality
e.preventDefault();
$(this).text('Calculating...')
setTimeout(function () {
var mytypes = ['flower', 'grass', 'rock', 'sand'];
responses=[];
for(var i=0; i < mytypes.length; i++)
{
urlrequest = '/myapi/'+mytypes[i];
jsonParams = JSON.stringify({"locationParams":{"name": ["myfirstparam", "mysecondparam"],
"value": [document.getElementsByName("amount_myfirstparam")[0].value, document.getElementsByName("amount_mysecondparam")[0].value]}})
$.ajax({
url:urlrequest,
method:'post',
data:jsonParams,
async:false,
success: function(data){
console.log('success of ajax response')
responses.push(data['value'].meanValue);
},
error: function(xhr, textStatus, errorThrown ) {
console.log(urlrequest);
}
});
}
delta = calculateDelta(responses);
displayImpact(delta);
$('#submitCall').text(' Update ');
}, 20);
});
});
In this case, the code does flower first, then push the result to responses, before moving on to grass, etc. All good, but as said, not ideal performance-wise.
Now, I'm trying to go asynchronous. And there, the queries get all completely mixed up whatever I do. I tried two main options that I thought should work:
Option1:
$(document).ready(function() {
//hang on event of form with id=myform
$("#submitCall").click(function(e) {
//prevent Default functionality
e.preventDefault();
$(this).text('Calculating...')
var mytypes = ['flower', 'grass', 'rock', 'sand'];
var async_request=[];
var responses=[];
for(var i=0; i < mytypes.length; i++)
{
urlrequest = '/myapi/'+mytypes[i];
jsonParams = JSON.stringify({"locationParams":{"name": ["myfirstparam", "mysecondparam"],
"value": [document.getElementsByName("amount_myfirstparam")[0].value, document.getElementsByName("amount_mysecondparam")[0].value]}})
async_request.push($.ajax({
url:urlrequest,
method:'post',
data:jsonParams,
success: function(data){
console.log('success of ajax response')
responses.push(data['value'].meanValue);
},
error: function(xhr, textStatus, errorThrown ) {
console.log(urlrequest);
}
}));
}
$.when.apply(null, async_request).done( function(){
// all done
console.log('all request completed')
console.log(responses);
});
});
});
Here, doing that gives me for example (somewhat inconsistent responses depending on the run):
flower --> grass response
grass --> flower response
rock --> flower response
sand --> sand response
I also tried:
Option2:
$(document).ready(function() {
//hang on event of form with id=myform
$("#submitCall").click(function(e) {
var mytypes = ['flower', 'grass', 'rock', 'sand'];
for (var i=0; i < mytypes.length; i++) {
var $typ = mytypes[i]
var $jsonParams = JSON.stringify({"locationParams":{"name": ["myfirstparam", "mysecondparam"],
"value": [document.getElementsByName("amount_myfirstparam")[0].value, document.getElementsByName("amount_mysecondparam")[0].value]}})
var fn = function(index){
$.ajax({
type: 'POST',
url: '/myapi/' + $typ,
data:$jsonParams,
success: function(data){
console.log(mytypes[index])
console.log(data)
}
});
};
fn(i);
}
});
});
And now, I'm still getting mixed up results, though it seems a bit "less" mixed.
flower --> flower response
grass --> grass response
rock --> grass response
sand --> sand response
So... What's up? I have no idea how to debug that mess, any hints are welcome.
EDIT:
Option3:
$(document).ready(function() {
//hang on event of form with id=myform
$("#submitCall").click(function(e) {
var jsonParams = JSON.stringify({"locationParams":{"name": ["myfirstparam", "mysecondparam"],
"value": [document.getElementsByName("amount_myfirstparam")[0].value, document.getElementsByName("amount_mysecondparam")[0].value]}})
$.when(ajaxcall('flower', jsonParams), ajaxcall('grass', jsonParams), ajaxcall('rock', jsonParams), ajaxcall('sand', jsonParams)).done(function(aflower, agrass, arock, asand){
console.log(aflower[0]);
console.log(agrass[0]);
console.log(arock[0]);
console.log(asand[0]);
});
});
});
function ajaxcall(typ, jsonParams) {
return $.ajax({
type: 'POST',
url: '/myapi/' + typ,
data: jsonParams
});
}
Following the comments, I also tried this, but again, results get mixed up, some queries just don't return any results, some return another api call response...
EDIT:
Option 4:
$(document).ready(function() {
//hang on event of form with id=myform
$("#submitCall").click(function(e) {
//prevent Default functionality
e.preventDefault();
$(this).text('Calculating...')
var jsonParams = JSON.stringify({"locationParams":{"name": ["myfirstparam", "mysecondparam"],
"value": [document.getElementsByName("amount_firstparam")[0].value, document.getElementsByName("amount_secondparam")[0].value]}})
var mytypes = ['flower', 'grass', 'rock', 'sand'];
var urls = [
'/myapi/flower',
'/myapi/grass',
'/myapi/rock',
'/myapi/sand'
]
var async_request=[];
var responses=new Array(mytypes.length);
for(var i=0; i < mytypes.length; i++)
{
urlrequest = urls[i];
let position = i;
async_request.push($.ajax({
url:urlrequest,
data:jsonParams,
method:'POST',
success: function(data){
console.log('success of ajax response')
console.log('position: ' + position);
console.log(data['typeString'])
console.log(mytypes[position])
responses[position] = data['myvalue'].meanValue;
},
error: function(xhr, textStatus, errorThrown ) {
console.log(urlrequest);
}
}));
}
$.when.apply(null, async_request).done( function(){
// all done
console.log('all request completed')
console.log(responses);
});
});
});
Using this, the order still gets messed up, though I feel that I can see the code "trying its best", very rarely it works (2 times out of 30ish "clicks"). Most of the time one or two queries returns blank, and the wrong response is used (data at the flower position is actually the grass response).
I have to assume that something funky is going on at the API interface level, which I do not control. Note that the API call is made through a VPN to a remote machine, running a GeoServer REST API inside a Tomcat with a jar Java web app doing the heavy lifting. In a synchronous setting, everything works great so it may be like tomcat setting a lock on the jar resources used by the API or something like that (I'm way out of my depth here!)