jQuery Ajax call in loop losing local variable reference - javascript

I am making several jQuery ajax calls within a loop. Each time one of the ajax calls return I need to reference a value corresponding to the original ajax call. My current code doesn't work properly, in that the value of the lskey variable has been altered by further loop iterations.
Here is the code:
for (var i = 0, len = localStorage.length; i < len; i++) {
var lskey = localStorage.key(i);
if (lskey.substr(0, 4) === 'form') {
var postdata = localStorage.getItem(lskey); // Get the form data
$.ajax({
type: "POST",
async: "false",
url: "/Profile/PostForm",
data: postdata,
success: function (data) {
$('#rollinginfo').append('<br>' + data + ',key=' + lskey);
localStorage.removeItem(lskey); // Remove the relevant localStorage entry
}
, error: function (data) { $('#rollinginfo').append('<br />ERR:' + data); }
});
}
}
The problem is that lskey is being altered each time the loop executes, and therefore the success callback does not have a reference to the value of lskey that existed at the time of the call.
How do I reference the correct value of lskey for each success callback?

for (var i = 0, len = localStorage.length; i < len; i++) {
var lskey = localStorage.key(i);
if (lskey.substr(0, 4) === 'form') {
var postdata = localStorage.getItem(lskey); // Get the form data
$.ajax({
type: "POST",
async: "false",
url: "/Profile/PostForm",
data: postdata,
local_lskey: lskey
success: function (data) {
$('#rollinginfo').append('<br>' + data + ',key=' + lskey);
localStorage.removeItem(this.local_lskey); // Remove the relevant localStorage entry
}
, error: function (data) { $('#rollinginfo').append('<br />ERR:' + data); }
});
}
}
This should work.

In the end I added the key info to the server posting, and then returned it from the server in JSON format so the success function could then simply refer to the key contained in the server response.

Have you considered chaining the AJAX calls? Basically you can make one AJAX call, process the result, modify lskey, etc. Then when you are ready, increment i and issue the second AJAX call. Loop this way instead of using the for loop...

You could put your ajax call into its own function and pass the lskey and postData values in. That way localStorage.removeItem(lskey) will refer to the lskey variable in the context of the function rather than the context of the loop.
Example
Declare the function -
function postForm(postdata, lskey) {
$.ajax({
type: "POST",
async: "false",
url: "/Profile/PostForm",
data: postdata,
success: function(data) {
$('#rollinginfo').append('<br>' + data + ',key=' + lskey);
localStorage.removeItem(lskey); // Remove the relevant localStorage entry
},
error: function(data) {
$('#rollinginfo').append('<br />ERR:' + data);
}
});
}
Then you can call your function from your loop -
for (var i = 0, len = localStorage.length; i < len; i++) {
var lskey = localStorage.key(i);
if (lskey.substr(0, 4) === 'form') {
var postdata = localStorage.getItem(lskey); // Get the form data
postForm(postdata, lskey);
}
}
You could also declare the function just before the loop (assigning it to a variable) and then call it within the loop.
var postForm = function(postdata, lskey) {
$.ajax({
type: "POST",
async: "false",
url: "/Profile/PostForm",
data: postdata,
success: function(data) {
$('#rollinginfo').append('<br>' + data + ',key=' + lskey);
localStorage.removeItem(lskey); // Remove the relevant localStorage entry
},
error: function(data) {
$('#rollinginfo').append('<br />ERR:' + data);
}
});
}
for (var i = 0, len = localStorage.length; i < len; i++) {
var lskey = localStorage.key(i);
if (lskey.substr(0, 4) === 'form') {
var postdata = localStorage.getItem(lskey); // Get the form data
postForm(postdata, lskey);
}
}

Related

Localstorage setting through ajax data randomly gets undefined

I am setting items to localstorage using the below code. The issue I am getting is whenever I refresh the page some of the items are not set when I inspect the localstorage it shows as undefined, this is absolutely random and sometimes all items are set parfectly. How can I ensure that all the items are set without any undefined?
const catdata = [];
var catArr = JSON.parse(localStorage.getItem('cat'));
for (let i = 0; i < catArr.length; i++) {
const catid = catArr[i]['id'];
const catname = catArr[i]['name'];
$('#topitems').prepend('<div ><a class="topitems" href="'+catArr[i]['id']+'">'+catArr[i]['name']+'</a></div>');
(function(i) {
$.ajax( { url : "sales/item_search_cat?cat="+catid
, data : "GET"
// , async: "false",
, dataType : "json"
, success : function(data) {
catdata.push(data);
localStorage.setItem(catid,JSON.stringify(catdata[i]));
}
});
})(i);
}
The execution of the ajax requests are not sequentially executed, and sometimes your code is accessing an index that doesn't exist.
For example, one response arrives with index 2, the code pushes into the empty array at index 0, and catdata[i] is trying to get the index 2.
I think you have to call the ajax request using await or you can use the data directly:
localStorage.setItem(catid, JSON.stringify(data));
Possible solution (I didn't test it):
The execution is async, if you need to wait for the executions, you have to follow an async/await approach.
function callAjax(catid) {
$.ajax({
url: "sales/item_search_cat?cat=" + catid,
data: "GET",
dataType: "json",
success: function(data) {
localStorage.setItem(catid, JSON.stringify(data));
success(data);
}
});
}
let catArr = JSON.parse(localStorage.getItem('cat'));
catArr.forEach(function({id: catid, name: catname}) {
$('#topitems').prepend('<div ><a class="topitems" href="' + catid + '">' + catname + '</a></div>');
callAjax(catid);
});

fetch the associative array particular value with its key name

i have a function . here i am passing an array applicationTabId = {"twitter": "15", "dropbox": "14"}; "}; I have an ajax success function .In this the variable appName name holds the key names as twitter , dropbox etc. I got this from database as ajax response. i want to find the value associated with this from the array. variable appName holding the key names and iam getting it from database as ajax response. i need to check the corresponding value of this name from array.
function getapplicationlogouturl(applicationTabId) {
chrome.storage.sync.get("endpoint", function (obj) {
FetchLogoutUrl = {
"applicationName": applicationTabId,
"sdcode": sdcode,
"type": "Chrome Fetch Application Logout Url"
};
$.ajax({
type: "POST",
url: obj.endpoint,
dataType: "json",
data: JSON.stringify(FetchLogoutUrl),
context: document.body,
timeout: globalTimeout,
success: function (response) {
if (response != null ) {
for (var i = 0; i < response.length; i++) {
var appName = response[i].name;
console.log(applicationTabId);
// o/p as {"twitter": "15", "dropbox": "14"}
console.log(appName);
//o/p as twitter
//dropbox
var tabid = applicationTabId.appName;
//var tabid = applicationTabId[appName];
console.log(tabid);
//o/p as undefined
console.log(appName+'---'+tabid);
if (appName in applicationTabId){
}
}
}
},
});
});
}
Apply loop like below:
$.each(applicationTabId, function(key,value){
console.log(key);
console.log(value);
});
Based on code you provided now, change your code like below:
function getapplicationlogouturl(applicationTabId) {
FetchLogoutUrl = {
"applicationName": applicationTabId,
};
$.ajax({
type: "POST",
url: obj.endpoint,
dataType: "json",
data: JSON.stringify(FetchLogoutUrl),
context: document.body,
success: function (response) {
if (response != null ) {
for (var i = 0; i < response.length; i++) {
var appName = response[i].name;
var tabid = applicationTabId[appName];
//print key value data in console to check working fine
console.log(appName+'---'+tabid);
}
}
},
});
}
Note:- var appName and var tabid value will be changed after each iteration happen.

How to handle an ajax request that uses a callback function that has an ajax request itself?

My main issue is that buildItem(data) returns 'undefined'. I've gone through some links on stackoverflow about how to do callback functions but I think that it's getting a bit messy since I'm going through multiple functions here.
I have a list that I'm appending to in this ajax call.
$.ajax({
dataType: "json,
url: "/retrieveTeamView.do?managerEmail=${email}",
cache: false,
success: function (data, status) {
$('#nestable ol').append(buildItem(data));
});
I defined buildItem() as such:
function buildItem(item) {
getTotalCost(item, function(totalCost) {
html += "<span>" + totalCost + "</span>";
return html;
}
}
So all buildItem does is it takes the data and passes it into getTotalCost.
Here my getTotalCost() function should take the item, as it has an attribute "email" that I need for the url, and it should do a loop through the data retrieved from the ajax call to return a totalCost.
function getTotalCost(item, callback) {
$.ajax({
dataType: "json",
url: "/retrieveUserUsage.do?email=" + item.email,
success: function(data) {
var totalCost = 0;
for (var i = 0; i < data.length; i++) {
totalCost += parseFloat(data[i].cost);
}
callback(totalCost);
}
});
}
My understanding is that callback(totalCost) returns back to buildItem() and returns the total cost successfully. From what I understand, doing alert(html) gives me a correct output in the alert dialog, but it is not successfully appended in the ajax function. Am I doing something wrong?
Note: I deleted chunks of details to keep the idea but to still keep the code secretive, so sorry if some parts may not seem like they're used.
I am thinking that the issue is related to the fact that AJAX calls are asynchronous. Therefore, it may be trying to update the DOM before everything is returned.
Therefore you need to nest the calls.
you could try something like this:
$.ajax({
dataType: "json,
url: "/retrieveTeamView.do?managerEmail=${email}",
cache: false,
success: function (data, status) {
$.ajax({
dataType: "json",
url: "/retrieveUserUsage.do?email=" + data.email,
success: function(data) {
var totalCost = 0;
for (var i = 0; i < data.length; i++) {
totalCost += parseFloat(data[i].cost);
}
$('#nestable ol').append("<span>" + totalCost + "</span>");
}
});
}
});

Cannot read property of undefined after JSON parse

I have done an ajax request in my code and it works good. After that I want to extract only the necessary info and re-post it to another script. Until now here is my code:
$.ajax({
type: "POST",
url: url,
data: {xhr_id: xhr_id},
success: function (jsondata) {
var product_data = [];
for (var i = 0; i <= 3; i++) {
//alert(jsondata.products[i].product_description.toSource());
product_data[i] = {};
product_data[i]["product" + i] = jsondata.products[i].product_description;
//alert(product_data[i]["product" + i].toSource());
}
},
dataType: "json"
});
The problem is that both the alerts work fine, displaying the information I want. However, I get an error message of "Uncaught TypeError: Cannot read property 'product_description' of undefined" which breaks the script and prevents me from doing anything else. What am I doing wrong, any ideas?
'product_description' of undefined" what it means is that your are trying to access property on undefined variable. That implies "jsondata.products[i]" resulted in undefined value which have occured due to index out of range.How many records are returned in jsondata 3 or 4,check and adjust the condition in for loop
The parameter in the success() function of $.ajax is a string. You have to put it through a parse function to make json. See your code below modified but not tested.
$.ajax({
type: "POST",
url: url,
data: {xhr_id: xhr_id},
success: function (jsondata) {
var oData;
try { oData=jQuery.parseJSON(jsondata) }
catch(err) {
alert("Problem parsing json string : " + jsondata)
return false
}
var product_data = [];
for (var i = 0; i <= 3; i++) {
//alert(oData.products[i].product_description.toSource());
product_data[i] = {};
product_data[i]["product" + i] = oData.products[i].product_description;
//alert(product_data[i]["product" + i].toSource());
}
},
dataType: "json"
});

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
}
})
});

Categories

Resources