"Synchrounous" AJAX call and web2py - javascript

I need some help with "synchronizing" my AJAX calls. I have a function scripted that takes in a file with certain test parameters and uses those parameters to kick off test via an AJAX call/s. The way the code is suppose to work is thatonce the test run is complete, another AJAX call is suppose to update the eventLog with the test results for that run and then move to the next iteration of the for loop.
The ajax calls can be seen in the for loop towards the bottom of the code. I looked into some documentation on using the jQuery Deffered class, but I am pretty new to JavaScript in general and I'm having trouble understanding how that code works. Thanks in advance for any help.
function runTest(modelName, serialNum, passArea) {
//Pull in sequence file
var str = "";
var table = document.getElementById('taskTable');
var output = document.getElementById('outputStrArea');
var passFail = document.getElementById(passArea).innerHTML;
var rowCount = table.rows.length;
for(var i=1; i<rowCount; i++) {
var row = table.rows[i];
str+= row.innerHTML+"\n";
}
str = str.split("<td>");
delete str[0];
delete str[-1];
//Create a list of tests that can be read out
var testList = [];
for (var i=1; i <str.length; i++){
str[i]= str[i].replace("</td>", "");
str[i]= str[i].replace(" ", "");
if (str[i].search("checkbox") < 0){
testList.push(str[i]);
}
}
var model = document.getElementById(modelName).innerHTML;
model = model.replace("<b>", "");
model = model.replace("</b>", "");
model = model.replace(" ", "");
var serial = document.getElementById(serialNum).innerHTML;
var info = model+" "+serial+" ";
for(var k=0; k<testList.length; k+=5){
info+= testList[k]+" "+testList[k+1]+" "+testList[k+2]+" "+testList[k+3]+" "+testList[k+4]+" ";
ajax("loadTestSequence?info="+info, [], passArea);
ajax("loadEventLog", [], 'eventLog');
}
}

The ajax calls have a success callback in which you can invoke another ajax call id you want. Syntax is something like this:
$.ajax({
url: url,
data: data,
success: function(){
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType
});
},
dataType: dataType
});
So now you can chain your respective ajax calls similarly. Hope that helps.

Related

Cannot read property 'length' of undefined AJAX

I have searched throughout SO about this issue, but I'm not getting any results in my code.
I have a simple JSON parser here, which creates a table based on a JSON object returned by an endpoint. Here is what I have tried so far.
function getAJAXData(APIurl){
$.ajax({
url: APIurl,
type: "GET",
dataType: "json"
}).then(function(data){
alert(data);
});
}
function generateTable(tableId){
var objRecords = getAJAXData("http://jsonplaceholder.typicode.com/posts");
var cols = addTableHeaders(objRecords, tableId);
for(var i = 0; i < objRecords.length; i++){
var tRow = $('<tr/>');
for (var colIdx = 0; colIdx < cols.length ; colIdx++){
var cellVal = objRecords[i][cols[colIdx]];
cellVal = (cellVal == null) ? "" : cellVal;
tRow.append($('<td/>').html(cellVal));
}
$(tableId).append(tRow);
}
}
function addTableHeaders(myList, tableId){
var colSet = [];
var headers = $('<tr/>');
for (var i = 0; i < myList.length; i++) {
var hRow = myList[i];
for(var key in hRow){
if($.inArray(key, colSet) == -1){
colSet.push(key);
headers.append( $('<th/>').html(key) );
}
}
}
$(tableId).append(headers);
return colSet;
}
That one doesn't work but when I hard-code a list, it generates a table from the hard-coded list. Can someone please explain what I am doing wrong or missing in the code? Thanks .
These two lines are an issue:
var objRecords = getAJAXData("http://jsonplaceholder.typicode.com/posts");
var cols = addTableHeaders(objRecords, tableId);
First off, your getAJAXData function doesn't return anything, so objRecords will always be undefined.
Second, even if it did return something, it's an asyncronous call, so the data won't be ready right away.
What you need to do is to wrap up the relevant bits of your code into a function and call it on the success callback so it gets executed only after your AJAX data is ready.
You need to call addTableHeaders inside of ajax success
$.ajax({
url: APIurl,
type: "GET",
dataType: "json",
success: function(data){
//call it here
}
})
});

Ajax Call in For Loop, For Loop Completing Before all Calls are Made

I have created a for loop that loops the number of times that an element appears in a container. The for loop grabs some data from the HTML and creates a JSON url which will then return a value. That value should then be added to the HTML in the appropriate place.
The problem seems that the for loop completes before all of the Ajax calls are made, so only the last value is being added to the HTML. I thought that I could make sure that the readystate is equal to 4, but that solution did not work. I also tried using complete, rather than success as an Ajax Event. Any insights? Here is my the code.
for(var index = 0; index < $('#wizSteps #step6 label').length; index++){
var priceCount;
console.log(index);
var currentSelect = $('#wizSteps #step6 label[data-pricepos="'+index+'"]');
url = 'http://www.thesite.com/api/search.json?taxonomy=cat3435' + currentSelect.find('input').attr('name');
jQuery.ajax({
url: url,
dataType: "JSON",
success: function( data ){
var totalResult = data.totalNumberOfResults;
console.log(currentSelect);
currentSelect.find('.itemCount').text(totalResult);
}
});
}
It looks like you don't necessarily need the requests to finish in order, you just need to keep track of currentSelect in a way that works. For that, you can use the context ajax option:
for (var index = 0; index < $('#wizSteps #step6 label').length; index++) {
var currentSelect = $('#wizSteps #step6 label[data-pricepos="' + index + '"]');
url = 'http://www.thesite.com/api/search.json?taxonomy=cat3435' + currentSelect.find('input').attr('name');
jQuery.ajax({
url: url,
dataType: "JSON",
context: currentSelect,
success: function (data) {
var totalResult = data.totalNumberOfResults;
this.find('.itemCount').text(totalResult);
}
});
}
That is ok, the calls are not supposed to be done this way. They are only initiated in the loop.
Ajax is asynchronous. The queries are completed later, may be in different order.
If you want to be sure that every call is completed before you do the next one,
you must integrate the next call into the callback function of the previous.
In your case the variable may be overwritten in the call back function.
You can learn more on this here:
Asynchronous Javascript Variable Overwrite
Another interesting question/discussion related to the topic:
What are the differences between Deferred, Promise and Future in JavaScript?
It does not directly answer your question, but helps to understand the problem deeper.
The point is that you probable don't need the loop at all (or you do but in a completely different form).
You should try creating a recursive function, that you will call again in the success of the ajax call, this way you will be sure that the next ajax call will be called only once the previous call is done.
If you want the requests in a sequence, you can work with a queue.
First build the queue:
var queue = [],
index,
stepLength = $('#wizSteps #step6 label').length;
for(index = 0; index < length; index++){
var priceCount;
console.log(index);
var currentSelect = $('#wizSteps #step6 label[data-pricepos="'+index+'"]');
url = 'http://www.thesite.com/api/search.json?taxonomy=cat3435' + currentSelect.find('input').attr('name');
queue.push([url, currentSelect]);
}
And after that do the serial ajax requests:
function serialAjax() {
if(queue.length === 0) {
return;
}
var queueData = queue.shift(),
url = queueData[0],
currentSelect = queueData[1];
jQuery.ajax({
url: url,
dataType: "JSON",
success: function( data ){
var totalResult = data.totalNumberOfResults;
console.log(currentSelect);
currentSelect.find('.itemCount').text(totalResult);
serialAjax();
}
});
};
// call the function
serialAjax();

Issues with Javascript For and Arrays

I'm trying to dynamically hide specific photos on a page, through Javascript, by selecting their data-id attribute and hiding the photo. This is being achieved through Ajax grabbing the IDs from a TXT file, splitting them in to an Array, and then using jQuery to hide the img with that ID. Note that this function is being passed through a setInterval every 3 seconds...
function getBlockedIDs() {
var stringData = $.ajax({
url: "http://s61892.gridserver.com/zone/twitter2/blocked.txt",
async: false
}).responseText;
var blockedArray = new Array();
blockedArray = stringData.split(",");
var length = stringData.length
for (var i = 0; i < length; i++) {
$('img.tweetphoto[data-id="' + stringData[i] + '"]').hide();
}
}
My problem is, it's not working! No errors are thrown from the console. What's wrong with my code? The idea behind this is to block specific (inappropriate) photos without reloading the page.
Any help is appreciated!
Are you sure you want to use stringData inside the for loop and not blockedArray? If so change the assignment to length also.
My version would look something like :
function getBlockedIDs() {
var blockedArray = $.ajax({
url: "http://s61892.gridserver.com/zone/twitter2/blocked.txt",
async: false
}).responseText.split (/\s*,\s*/);
for (var i = blockedArray.length; i--;) {
$('img.tweetphoto[data-id="' + blockedArray[i] + '"]').hide();
}
}
I would do something like:
function getBlockedIDs() {
$.get("http://s61892.gridserver.com/zone/twitter2/blocked.txt", function(stringData) {
var blockedArray = stringData.split(/\s*,\s*/);
for (var i = 0; i < blockedArray.length; i++) {
$('img.tweetphoto[data-id="' + blockedArray[i] + '"]').hide();
}
});
}

Use a FOR loop within an AJAX call

So, what i'm trying to do is to send an AJAX request, but as you can see i have many fields in my form, and i use an array to make validations, i would like to use the same array, to pass the values to be sent via AJAX:
I never used the for loop in JS, but seems familiar anyway.
The way the loop is made, obviously wont work:
for (i=0;i<required.length;i++) {
var required[i] = $('#'+required[i]).attr('value');
This will create the variables i want, how to use them?
HOPEFULLY, you guys can help me!!! Thank you very much!
required = ['nome','sobrenome','endereco','codigopostal','localidade','telemovel','email','codigopostal2','localidade2','endereco2','nif','entidade','codigopostal3','localidade3','endereco3','nserie','modelo'];
function ajaxrequest() {
for (i = 0; i < required.length; i++) {
var required[i] = $('#' + required[i]).attr('value');
var dataString = 'nome=' + required[0] + '&sobrenome=' + required[1];
}
$.ajax({
type: "POST",
url: "ajaxload/como.php",
data: dataString,
success: function() {
$(".agendarleft").html("SUCESS");
}
});
To help ensure that the appropriate element IDs and values are passed, loop through the various elements and add the data to an object first.
jQuery:
required = ['nome', 'sobrenome', 'endereco', 'codigopostal', 'localidade', 'telemovel', 'email', 'codigopostal2', 'localidade2', 'endereco2', 'nif', 'entidade', 'codigopostal3', 'localidade3', 'endereco3', 'nserie', 'modelo'];
function ajaxrequest() {
var params = {}; // initialize object
//loop through input array
for (var i=0; i < required.length; i++) {
// set the key/property (input element) for your object
var ele = required[i];
// add the property to the object and set the value
params[ele] = $('#' + ele).val();
}
$.ajax({
type: "POST",
url: "ajaxload/como.php",
data: params,
success: function() {
$(".agendarleft").html("SUCESS");
}
});
}
Demo: http://jsfiddle.net/kPR69/
What would be much cleaner would be to put a class on each of the fields you wish to save and use this to iterate through them. Then you wouldn't need to specify the input names either and you could send a json object directly to the Service;
var obj = {};
$('.save').each(function () {
var key = $(this).attr('id');
var val = $(this).val();
if (typeof (val) == "undefined")
val = "''"
obj[key] = val;
}
Then send obj as the data property of your AJAX call....
There are a few issues with your code. 'required' is being overwritten and is also being re-declared inside of the loop.
I would suggest using pre-written library, a few I included below.
http://jquery.malsup.com/form/#validation
https://github.com/posabsolute/jQuery-Validation-Engine
Otherwise the follow would get you close. You may need to covert the array into a string.
var required = ['nome','sobrenome'];
function ajaxrequest() {
var values;
for (i = 0; i < required.length; i++) {
var values[i] = $('#' + required[i]).attr('value');
}
$.ajax({
type: "POST",
url: "ajaxload/como.php",
data: values,
success: function() {
$(".agendarleft").html("SUCESS");
}
});
}

JavaScript auto-incrementing a variable in jQuery and AJAX

I have JavaScript using jQuery and AJAX which creates a dynamic array, which has some values used for AJAX request as below;
<script type="text/javascript">
var array = Array("y","y","x","y","y","y");
function updateBackground(cellId, titleId) {
var i = 0;
$.ajax({
type: "POST",
url: "ajax.php",
data: {
filename: Array(array[i], "testdata", $("#"+titleId).html())
},
success: function(response){
$("#"+cellId).css("background-image", "url('pdfthumb/" + response + "')");
}
});
i++;
}
</script>
The script is suppose to submit values in the array in array[i] for each AJAX request. I made a variable var i which auto increments.. But the script is not working.. The script works well if array[i] is replaced by array[0] or array[1] etc..
How can I solve the syntax error?
Every time you call updateBackground() i = 0 (again). May be you must initialize i outside of the function.
What happens if i > array.length? And I would rename the variable.
You don't have an iterator. Your variable i gets set to 0 every time the function runs. The increment at the end is useless.
Maybe you need something like this?
var array = Array("y","y","x","y","y","y");
function updateBackground(cellId, titleId) {
for( var i = 0; i < array.length; i++ ) {
$.ajax({
type: "POST",
url: "ajax.php",
data: {
filename: Array(array[i], "<?php echo $dir; ?>", $("#"+titleId).html())
},
success: function(response){
$("#"+cellId).css("background-image", "url('pdfthumb/" + response + "')");
}
});
}
}
Each time you call updateBackground() function, the i variable is being reinitialized. It's just a local variable and as soon as the function finishes it's being destroyed by GC. You could do something like this:
var UpdateBackground = {
array: [..],
counter: 0,
doUpdate: function(cellId, titleId) {
// AJAX request
this.counter++;
}
};
UpdateBackground.doUpdate(1, 1);
UpdateBackground.doUpdate(1, 1);
I think that you should send the whole array maybe as a commaseparated string and instead and make just one ajax request, because http-requests are expensive and change the server side code accordingly. And fetch the cellids as an array.
If you think that you have a long list or a table it can be like a lot of requests. Do the stuff in client code and do the stuff in server code and keep the number of http-requests as few as possible.
And use the join method on the array.
var arr = [ 'y', 'y' ];
arr.join(',');
// outputs y, y
I fixed it... Thank you so much #Jed, #Pointy, #Crozin, and #Lord Vader for helping me to figure it out.... :)
I just take var i = 0; outside the loop.... above var array like;
var i = 0;
var array = Array("y","y","x","y","y","x");

Categories

Resources