AJAX Jquery: execution order of events - ajax

I have a webpage with different elements (a list of links and two select boxes) connected between them. Clicking on them may affect one of the other element and all of their values contribuite to update a value to show on the page.
So, the code is this:
$(document).ready(function() {
var someVar = '';
$("select#size").bind('change', function() {
someVar = $(this).val();
console.log('first');
});
my_change();
console.log('second' + someVar);
});
function my_change() {
$.getJSON("photos/change_product", {json_stuff}, function(data) {
var options = [];
for (var i = 0; i < data.length; i++) {
options.push('<option value="' + data[i].id + '">' + data[i].label + '</option>');
}
$("select#size").trigger('change');
$("select#options").html(options.join('')).trigger('change');
})
};
};
When I load the page the my_change function is called. It does some stuff and then triggers a change event on a select-box. I need to update a value using what's inside this select box and only then let the execution to proceed. So what I need this code to do would be to print 'first', and then 'second' with the value of the variable. What actually happen is that it prints 'second' 'first'.
I think it's because I'm doing asynchronous calls. What can I do?

There's several ways to do this.
You could use jQuery $.when and call the console.log after the ajax response finishes.
$(document).ready(function() {
var someVar = '';
$("select#size").bind('change', function() {
someVar = $(this).val();
console.log('first');
});
$.when( my_change() ).then(function(){
console.log('second' + someVar);
});
});
function my_change() {
return $.getJSON("photos/change_product", {json_stuff}, function(data) {
var options = [];
for (var i = 0; i < data.length; i++) {
options.push('<option value="' + data[i].id + '">' + data[i].label + '</option>');
}
$("select#size").trigger('change');
$("select#options").html(options.join('')).trigger('change');
})
};
};
Or you could add a callback argument to the my_change(callback) function.
$(document).ready(function() {
var someVar = '';
$("select#size").bind('change', function() {
someVar = $(this).val();
console.log('first');
});
my_change(function(){ console.log('second' + someVar) } );
});
function my_change(callback) {
return $.getJSON("photos/change_product", {json_stuff}, function(data) {
var options = [];
for (var i = 0; i < data.length; i++) {
options.push('<option value="' + data[i].id + '">' + data[i].label + '</option>');
}
$("select#size").trigger('change');
if( typeof callback !== 'undefined' && typeof callback === 'function' )
callback();
$("select#options").html(options.join('')).trigger('change');
})
};
};

The 'second' console.log() is being called first since the asynchronous $.getJSON() call waits for the response from the server before firing its callback function. You could save the jqXHR object to a variable and then use that to run your 'second' consone.log() with $.when():
$(function() {
var someVar = '';
$("#size").on('change', function() {//on() is the same as bind() here
someVar = $(this).val();
console.log('first');
});
//save the jQuery XHR object from your $.getJSON request
var jqXHR = my_change();
//when the above jQuery XHR object resolves, it will fire the second console.log
$.when(jqXHR).then(function () {
console.log('second' + someVar);
});
});
function my_change() {
//here we return the jQuery XHR object for the $.getJSON request so we can run code once it resolves
return $.getJSON("photos/change_product", {json_stuff}, function(data) {
var options = [];
for (var i = 0; i < data.length; i++) {
options.push('<option value="' + data[i].id + '">' + data[i].label + '</option>');
}
$("#size").trigger('change');
$("#options").html(options.join('')).trigger('change');
})
};
Here is documentation for $.when(): http://api.jquery.com/jquery.when
A quick side-note: it is generally slower to add a tag-type to a selector, especially when you are selecting IDs as that is already a very fast method of selecting elements.

Any code that relies on the response of the getJSON must be placed in, or called from, the getJSON callback.
That's what a callback is for.
You should note that your my_change function will not have access to the someVar variable because it is local to the ready() callback.
To remedy this, move the my_change function inside the ready() callback.
Or just pass a function directly to my_change.
my_change(function() {
console.log('second' + someVar);
});
And have the getJSON callback invoke the function.
function my_change( func ) {
$.getJSON("photos/change_product", {json_stuff}, function(data) {
var options = [];
for (var i = 0; i < data.length; i++) {
options.push('<option value="' + data[i].id + '">' + data[i].label + '</option>');
}
$("select#size").trigger('change');
$("select#options").html(options.join('')).trigger('change');
func();
});
}

Related

Parallel asynchronous Ajax calls from the client

I have 20 data packet in the client and I am pushing one by one to the server via Ajax post. Each call take approximately one minute to yield the response. Is there any way to make few of these requests run parallel.
I have used Jquery promise. However, still the request waiting for the prior one to get completed.
var dataPackets=[{"Data1"},{"Data2"},{"Data3"},{"Data4"},{"Data5"},
{"Data6"},{"Data7"},{"Data8"},{"Data9"},{"Data10"},
{"Data11"},{"Data12"},{"Data13"},{"Data14"},{"Data15"},{"Data16"},
{"Data17"},{"Data18"},{"Data19"},{"Data20"}];
$(dataPackets).each(function(indx, request) {
var req = JSON.stringify(request);
setTimeout({
$.Ajax({
url: "sample/sampleaction",
data: req,
success: function(data) {
UpdateSuccessResponse(data);
}
});
}, 500);
});
The when...done construct in jQuery runs ops in parallel..
$.when(request1(), request2(), request3(),...)
.done(function(data1, data2, data3) {});
Here's an example:
http://flummox-engineering.blogspot.com/2015/12/making-your-jquery-ajax-calls-parallel.html
$.when.apply($, functionArray) allows you to place an array of functions that can be run in parallel. This function array can be dynamically created. In fact, I'm doing this to export a web page to PDF based on items checked in a radio button list.
Here I create an empty array, var functionArray = []; then based on selected items I push a function on to the array f = createPDF(checkedItems[i].value)
$(document).ready(function () {
});
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function exportPDFCollection() {
var f = null;
var x = 0;
var checkedItems = $("input:checked");
var count = checkedItems.length;
var reportList = $(checkedItems).map(
function () {
return $(this).next("label").text();
})
.get().join(",");
var functionArray = [];
var pdf = null;
for (var i = 0; i < count; i++) {
f = createPDF(checkedItems[i].value)
.done(function () {
pdf = checkedItems[x++].value;
alert('PDF => ' + pdf + ' created.');
})
.fail(function (jqxhr, errorText, errorThrown) {
alert('ajax call failed');
});
functionArray.push(f);
}
$.when.apply($, functionArray)
.done(function () {
$.get("http://yourserver/ExportPage.aspx",{reports: reportList})
.done(function () {
alert('PDF merge complete.');
})
.fail(function (jqxhr, errorText, errorThrown) {
alert('PDF merge failed. Please try again.');
});
return true;
});
}
function createPDF(webPage) {
return $.get(webPage);
}

AJAX dropdown list down not update with var string variable

I have a test script to update a county drop down list whenever the year or state is updated. When I used a literal string when year is selected, the county list updated fine. However when I tried to the county list using an ajax call and used a (var options) to build the list, the drop down list value changed to an empty list even though I verified the value of (var options) contains valid drop down list options.
Please help!
Thanks,
$('#State').on("change", function () {
var state = $('#State').val();
var year = $('#Year').val();
var obj = {
state: state,
year:year
};
alert("State changed:" + state + ":" + year);
AjaxCall('/RIC/GetCounties', JSON.stringify(obj), 'POST').done
(function (response) {
if (response) {
$('#DataId').html("<option value='test'>Test</option>");
var options = '';
options += "<option value='Select'>Select</option>\n";
for (i in response) {
options += "<option value='" + response[i].DataId + "'>" + response[i].County + "</option>\n";
}
$('#DataId').html("<option value='Select'>Select-S</option><option value='16'>Alameda-S</option>");
alert("Statitical Areas(S): " + options);
//$('#DataId').html(options); //This should work. How to get the value of options into the string
//$('#DataId').append(options);
}
}).fail(function (error) {
alert("County Error:" + error.StatusText);
});
});
$('#Year').on("change", function () {
var state = $('#State').val();
var year = $('#Year').val();
var obj = {
state: state,
year: year
};
alert("Year changed:" + state +":"+ year);
AjaxCall('/RIC/GetCounties', JSON.stringify(obj), 'POST').done
(function (response) {
if (response) {
$('#DataId').html("<option value='test'>Test</option>");
var options = '';
options += "<option value='Select'>Select</option>\n";
for (i in response) {
options += "<option value='" + response[i].DataId + "'>" + response[i].County + "</option>\n";
}
//$('#DataId').html("<option value='Select'>Select-Y</option><option value='16'>Alameda-Y</option>");
$('#DataId').html(options); //This should work. How to get the value of options into the string
alert("Statitical Areas(Y): " + options);
//$('#DataId').append(options);
}
}).fail(function (error) {
alert("County Error:" + error.StatusText);
});
});
});
function AjaxCall(url, data, type) {
  return  $.ajax({
     url:  url,
     type:  type  ?  type  :  'GET',
     data:  data,
     contentType:  'application/json'
   });
}  
Instead of using another function to call your $.ajax why not call it immediately. There’s no performance improvement on what you had done. Try to revert your code and just add async property if you want to wait the response before proceeding to your lower conditions.
I hope this will help you

Dragula not sending AJAX request

I am using the following code to sort the rows of a table based on Ids. I am using Dragula for drag and drop functionality. The Sorted Ids is presented in the variable sortedIDs. The alert present within if(sortedIDs) is showing an alert, but no request is being sent using AJAX.
var container = document.getElementById('tb');
var rows = container.children;
var nodeListForEach = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]);
}
};
var sortableTable = dragula([container]);
var pingu='';
sortableTable.on('dragend', function() {
nodeListForEach(rows, function (index, row) {
//alert(row.id);
pingu=pingu+','+row.id;
//alert(pingu);
// row.lastElementChild.textContent = index + 1;
// row.dataset.rowPosition = index + 1;
});
var sortedIDs=pingu;
pingu='';
// alert (sortedIDs);
if (sortedIDs) {
alert(sortedIDs);
$.ajax({
type: 'GET',
url: '<?php echo $site_url . 'index.php/API/p2376ghDSPOLWYBdhBT'?>',
data: 'lmqSPOEhyVt87H6tBYSfdreg=' + sortedIDs + '&hjhqweuty87685gh87GCfsc6HF=' + sbds98JWUDGHKJ98yujg,
success: function (tata) {
alert (tata);
if (tata == '1') {
$("#success").show();
$('#success').delay(2000).fadeOut('slow');
} else {
$("#failure").show();
$('#failure').delay(5000).fadeOut('slow');
}
}
});
} else {
//$('#ms').html('<option value="">Select Q level first</option>');
}
});
And when i am adding
error : function(jqXHR, textStatus, errorThrown){
}
for showing AJAX error, it starts throwing the alert too.
Any sort of help would be deeply appreciated.
Thanks
I solved the problem. I forgot to retrieve the value of an attribute and send it to the API.
var sbds98JWUDGHKJ98yujg = $('#p2JMopns3hfBubNNHJeer').val();

Parsing JSON with AJAX - show random item of the JSON and update after an amount of time

I'm able to parse JSON with ajax, but at the moment it shows all the names out of the JSON.
I want only one name viewed and after an amount of time I want another one viewed and so on..
Ajax code:
$(document).ready(function(){
parseJson();
});
function parseJson(){
$.ajax({
url : 'data/members.json',
dataType : 'json',
success : function(data) {
succes(data);
},
error: function(){
window.alert("error");
}
});
};
function succes(dataObj){
var counter = 1;
$.each(dataObj.Members.Member, function(indexData, valueData){
var htmlString = "";
htmlString += '<article class="memberInfo" data-object="' + counter + '">';
htmlString += "<div class=''><p>" + valueData.Firstname + ' ' + valueData.Surname + "</p></div>";
htmlString += "</article>";
$("#members").append(htmlString);
counter++;
});
}
Rather than use .append you can use .html and set a staggering timeout so that it cycles through the names that get displayed:
var timer = 0;
$.each(...
setTimeout(function () {
var htmlString = "";
/* snip */
$("#members").html(htmlString);
}, timer + (indexData * 2000));
});

Get the variable of a json request outside the function (jquery)

I feel pretty stupid asking this but how can I get the variable crdnts outside the function
$(function() {
var coordinates = {
LoadDefault: function() {
$.getJSON('http://api.wipmania.com/jsonp?callback=?', '', function(json) {
var crdnts = json.latitude + "," + json.longitude;
//alert(crdnts);//this works
return crdnts;
});
}
};
alert(coordinates.LoadDefault());//I would like to get the crdnts variable here.
});
or
http://jsfiddle.net/stofke/Lv3YD/
javascript ajax is asynchronous. so you need to use callbacks:
$(function() {
var coordinates = {
LoadDefault: function() {
$.getJSON('http://api.wipmania.com/jsonp?callback=?', '', function(json) {
var crdnts = json.latitude + "," + json.longitude;
call_alert(crdnts); //callback
});
}
};
function call_alert(cr){
alert(cr);
}
coordinates.LoadDefault();
});
You can't. Your Ajax call is asynchronous, so you cannot predict when will it return.
The only thing you can do is doing something with it in the success callback, or set your Ajax to be synchronous if it is a choice (in this case all JS execution will wait until the request is finished).
For example, you can call a function when the Ajax call successfully finished:
$(function() {
var coordinates = {
LoadDefault: function() {
$.getJSON('http://api.wipmania.com/jsonp?callback=?', '', function(json) {
var crdnts = json.latitude + "," + json.longitude;
callSomething(crdnts);
});
}
};
function callSomething(x) {
alert(x);
}
});

Resources