I am running a loop function with an AJAX request inside it, and the success function on the AJAX need to access a counter variable outside of the loop function, but it wont access it.
var updateCount = 10;
var runCount = 0;
$('#main-table .changed').not("[value='0']").closest('tr').each(function(e){
if($(this).closest('tr').find('.changed').val() == 1){
var row = $(this).closest('tr');
var notes = row.find('input[name="notes"]').val();
var category = row.find('select[name="category"]').val();
var fileId = row.find('select[name="file"]').val();
var fileRow = row.find('.file-id').val();
var quarter_id = row.find('.quarter-id').val();
$.ajax({
url: '/myurl',
type: "POST",
data: {_token: CSRF_TOKEN, 'file_row' : fileRow, 'files' : fileId, 'notes': notes, 'category' : category, 'type' : type, 'quarter': quarter_id, 'row_count':updateCount},
success: function(data){
if(data == 0){
console.log("yes");
//I need to increment the runcount here, but it wont increment
runCount++;
}
}
});
//If i increment the run count here outside the AJAX request, it works
runCount++;
if(runCount == updateCount){
console.log("Done");
}
};
});
As stated in the notes, i need to access the runCount variable inside the ajax success function, but I cant. It works fine if I access it just outside of the AJAX request.
Just to confirm, the ajax request is working, as it is console logging yes for each time, so I cant see why it wouldn't increment?
there is likely a better way to do it, but one sure-fire way is to make another function (in javascript) and update it with that, like:
function bumpRunCount(){
runCount++;
}
then call that function from the ajax result. That of course is dependent on the scope of runCount. I only mention that because you mention a function, and I dont see one, so it is possible that you are only showing a part of the function. If that is the case, you will need to make sure var runCount is part of the global namespace; or at least accessible.
To avoid this scope problem try this, try parsing the variable inside the loop function
var runCount = 0;
$('#main-table .changed').not("
[value='0']").closest('tr').each((runCount)=>{
if($(this).closest('tr').find('.changed').val() == 1){
var row = $(this).closest('tr');
var notes = row.find('input[name="notes"]').val();
var category = row.find('select[name="category"]').val();
var fileId = row.find('select[name="file"]').val();
var fileRow = row.find('.file-id').val();
var quarter_id = row.find('.quarter-id').val();
$.ajax({
url: '/myurl',
type: "POST",
data: {_token: CSRF_TOKEN, 'file_row' : fileRow, 'files' :
fileId, 'notes': notes, 'category' : category, 'type' :
type,
'quarter': quarter_id, 'row_count':updateCount},
success: function(data){
if(data == 0){
console.log("yes");
//I need to increment the runcount here, but it wont increment
runCount++;
}
}
});
//If i increment the run count here outside the AJAX request, it
works
//runCount++;
};
});
Related
This js loop script always get the last value of ui_item inside a jquery ajax funciton. How can a catch the correct value of each iteration?
for (var i = 0; i <= split_files_cb_value_holder.length - 1; i++){
var split_values = split_files_cb_value_holder[i].split(':');
ui_item = split_files_cb_value_holder[i];
$.ajax({
type: "POST",
url: "ds/index.php/playlist/check_folder",
data: "component_type="+$('#component_type').val()+"&value="+split_values[1],
success: function(msg)
{
console.log(ui_item); //ALWAYS GETS THE LAST VALUE
},
error: function()
{
alert("An error occured while updating. Try again in a while");
}
});
}
Thanks!
The problem is that the anonymous callback method captures the ui_item variable by reference. Since there is only one variable, it always gets whatever was assigned last to the variable.
You need to wrap the contents of the for loop in a function that takes i as a parameter, then call the function in the loop. Each call to the wrapper function will create a separate variable, solving the problem.
For example:
function doCheck(i) {
var split_values = split_files_cb_value_holder[i].split(':');
var ui_item = split_files_cb_value_holder[i];
$.ajax({
type: "POST",
url: "ds/index.php/playlist/check_folder",
data: "component_type="+$('#component_type').val()+"&value="+split_values[1],
success: function(msg)
{
console.log(ui_item); //Don't always get the last value
},
error: function()
{
alert("An error occured while updating. Try again in a while");
}
});
}
for (var i = 0; i < split_files_cb_value_holder.length; i++)
doCheck(i);
Turn async off, it will fix the problem i guess. I mean add this: async:false
I have an array noti_array which has two elements, noti_array[0]='meghan&3', noti_arra[1]='tylor&5', the username and number concatenated by '&', in each iteration, I want to send the username to a ajax request
for(var i=0;i<noti_array.length;i++)
{
var mesg_array = new Array();
mesg_array=noti_array[i].split('&');
who_sent=mesg_array[0]; //first iteration, meghan
sent_num=mesg_array[1]; //3
//send the user name to a ajax request
$.ajax({
url:'getLastCon.php',
method:'post',
data:{who_sent:who_sent},
success:function(data){
alert(who_sent);
}
});
}
this code above would not alert meghan and tylor, instead, it alerts twice tylor, and if I use a 'break' after the ajax request, it would alert meghan once only, I think it's probably the loop enter the next iteration even the ajax request have not completed
It looks like who_sent could be a global variable. In that case, because of the asynchronous nature of your AJAX calls, the alert would trigger for the last assigned value of who_sent. Make who_sent a local variable or add another variable by adding var: var who_sent = mesg_array[0];.
Edit:
The above is wrong on how variables persist in a loop. I'm sorry for the inaccurate info. The following code will do what you want:
for( var i=0 ; i < noti_array.length ; i++ ) {
var mesg_array = noti_array[i].split('&');
who_sent = mesg_array[0]; //first iteration, meghan
sent_num = mesg_array[1]; //3
(function(who) {
//send the user name to a ajax request
$.ajax({
url: 'getLastCon.php',
method: 'post',
data: { who_sent:who },
success: function(data) {
alert(who);
}
});
})(who_sent);
}
I'm using ajax to retrieve a set url and am getting a piece of information from the HTML of the site.
This much is working but when I try to use the variables that I set within the ajax they remain undefined. I know that ajax isn't the best way to do this, but I have a very short time to get this working and this method seems to be working the best out of everything else I've tried.
Heres the code I'm using:
function getPrice() {
alert("Getting Price");
$.ajax( {
url: URL,
type: "GET",
datatype:"html",
success: function(result) {
$('#holder').html($(result));
var textcontents = $('#holder').find('td').text();
var target = textcontents.split("\n");
Price = target[3];
price = Price;
alert(price);
return price;
}
});
db.transaction(updatePrice, successCB, errorCB);
}
The price variable is attempted to be passed to the updatePrice function, but this error with the message Sql error Undefined, Undefined, as it doesn't appear to be passing the variables across. Any help would be greatly appreciated.
(function() {
var price; //this will be available anywhere within this scope
function getPrice() {
alert("Getting Price");
$.ajax( {
url: URL,
type: "GET",
datatype:"html",
success: function(result) {
$('#holder').html($(result));
var textcontents = $('#holder').find('td').text();
var target = textcontents.split("\n");
price = target[3]; // lets set the price variable here
alert(price);
}
});
db.transaction(updatePrice, successCB, errorCB);
}
// rest of your application code goes here
}());
Now make sure that you are passing the price variable to the updatePrice function.
I am working with jQuery and doing some prototyping.
In my app, I use jQuery.ajax() to get some HTML from the server, then it needs to be inserted into a DIV in the page.
Here are the relevant parts of my code:
SONGS_UPLOADER.prototype.FileSelectHandler = function(e) {
this.FileDragHover(e);
var files = e.target.files || e.dataTransfer.files;
var target = this.target;
var artist_id = this.artist_id;
var album_id = this.album_id;
var onComplete = this.onSongUploaded;
for ($x = 0; $x < files.length; $x ++) {
var file = files[$x];
jQuery.ajax({
type: 'post',
dataType : 'html',
url: ajaxurl,
data: {action: 'add_new_song', artist_id: artist_id, album_id: album_id, title:file.name},
success: function(DATA)
{
onComplete(DATA);
}
});
}
}
SONGS_UPLOADER.prototype.files;
SONGS_UPLOADER.prototype.onComplete;
SONGS_UPLOADER.prototype.album_id;
SONGS_UPLOADER.prototype.artist_id;
SONGS_UPLOADER.prototype.target;
SONGS_UPLOADER.prototype.onSongUploaded = function(DATA){
var song = jQuery(DATA);
//console.log(target.find('.songs_list'));
this.target.find('.songs_list').append(song);
new SONGS_MANAGER(song, file);
}
In the AJAX complete function I have tried the following:
onComplete(DATA) - this calls the onSOngUploaded function, but the 'this.target' in onSongUploaded is undefined.
this.onSongUploaded and onSongUploaded - got an error that onSongUploaded does not exist.
jQuery.proxy(this.onSongUploaded (and) onSongUploaded, this) - got an error that onSOngUploaded does not exist.
I know it probably has something to do with the scope when using the jQuery.ajax() function, but I just can't figure out how to resolve it.
How can I adjust my code so the onSongUploaded function is called and respects the 'this' keyword on the SONGS_UPLOADER object?
I'm not quite sure why my code's output changes when I move the console.log() into the second AJAX call.
By splitting the three console.logs between the two AJAX calls, this code returns what I want (all productTitles with their productURLs and numProductTopics):
http://pastie.org/8067201
But after moving all three console.logs into the second AJAX call, this code returns the same productTitle and productURL every time with the differing, desired numProductTopics:
http://pastie.org/8067203
Could someone please explain?
This is because you have a for loop where you assign value to your variables and start an ajax call, which will get executed before your ajax success callback executes. So they will hold the value of that last iteration.
for (var i=0;i < results.data.length; i++) {
var object = results.data[i];
if (object.canonical_name && object.name) {
var productTitle = object.name;
productURL = "getsatisfaction.com/trinet/products/" + object.canonical_name;
jQuery.ajax({
type: 'GET',
url: apiBaseURL + 'topics.json?product=' + object.canonical_name,
dataType: 'jsonp',
success: function(results2) {
var numProductTopics = results2.total;
console.log(productTitle); //<-- this will have the value from last iteration
console.log(productURL);//<-- this will have the value from last iteration
console.log(numProductTopics);
}
});
}
You can also resolve it by enclosing the variables for each loop int the ajax call by making it a function invocation. bacically you want to lockin the variables as closure variables for each iteration.
for (var i=0;i < results.data.length; i++) {
var object = results.data[i];
if (object.canonical_name && object.name) {
var productTitle = object.name;
productURL = "getsatisfaction.com/trinet/products/" + object.canonical_name;
(function(productTitle, productURL){ //<-- Take the arguments
jQuery.ajax({
type: 'GET',
url: apiBaseURL + 'topics.json?product=' + object.canonical_name,
dataType: 'jsonp',
success: function(results2) {
var numProductTopics = results2.total;
console.log(productTitle);
console.log(productURL);
console.log(numProductTopics);
}
});
})(productTitle, productURL); //Lock in the variables here invoking the function call.
}
FIddle