Node.js callback within a loop has wrong iterator value [duplicate] - javascript

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
for(var i in companyTickerList) {
console.log('i = ' + i);
//construct url
var url = base_url + companyTickerList[i];
console.log('url = ' + url);
request(url, function(error, response, xml) {
if(!error && response.statusCode == 200) {
//load xml returned from GET to url
var cik_xml = cheerio.load(xml)
console.log('i = ' + i);
//map company ticker symbol to cik value scraped from xml
TickerToCIK[companyTickerList[i]] = cik_xml('company-info cik').text();
console.log('TICKER = ' + companyTickerList[i] + ' CIK = ' + cik_xml('company-info cik').text());
}
}
//CONSOLE LOG OUTPUT
i = 0
http://www.sec.gov/cgi-bin/browse..........SNPS
i = 1
http://www.sec.gov/cgi-bin/browse..........IBM
i = 2
http://www.sec.gov/cgi-bin/browse..........BA
i = 3
http://www.sec.gov/cgi-bin/browse..........GM
i = 4
http://www.sec.gov/cgi-bin/browse..........F
i = 5
http://www.sec.gov/cgi-bin/browse..........C
i = 6
http://www.sec.gov/cgi-bin/browse..........CVX
i = 6
TICKER = CVX CIK = 0000883241
i = 6
TICKER = CVX CIK = 0000037996
i = 6
TICKER = CVX CIK = 0000831001
i = 6
TICKER = CVX CIK = 0000093410
i = 6
TICKER = CVX CIK = 0001467858
i = 6
TICKER = CVX CIK = 0000012927
i = 6
TICKER = CVX CIK = 0000051143
Why is the iterator value i always equivalent to 6 in the callback function after each request call is triggered? It is making the keys for my TickerToCIK map always be CVX. Do I need to pass i as an argument to the callback function?

var is tricky :)
JavaScript actually evaluates your code like this:
var i;
for(i in companyTickerList) {
console.log('i = ' + i);
// ...
meaning, it's like var definition executed before your first line of code.
So, you actually have a variable i which gets updated 6 times and eventually i = 6.
Your request() callback is async, and by the time your first callback actually got invoked, the loop is long gone and i equals 6.
Solution:
One possible solution is to use an IIFE (Immediately-Invoked Function Expression).
That is:
(function (i) {
// async code using i
})(i);
Like so:
for (var i in companyTickerList) {
console.log('i = ' + i);
//construct url
var url = base_url + companyTickerList[i];
console.log('url = ' + url);
(function (i) {
request(url, function (error, response, xml) {
if (!error && response.statusCode == 200) {
//load xml returned from GET to url
var cik_xml = cheerio.load(xml);
console.log('i = ' + i);
//map company ticker symbol to cik value scraped from xml
TickerToCIK[companyTickerList[i]] = cik_xml('company-info cik').text();
console.log('TICKER = ' + companyTickerList[i] + ' CIK = ' + cik_xml('company-info cik').text());
}
});
})(i);
}

You will need to use a closure to implement this correctly. For example, something like this.
for(var i in companyTickerList) {
console.log('i = ' + i);
//construct url
var url = base_url + companyTickerList[i];
console.log('url = ' + url);
function(i){
request(url, functon(error, response, xml) {
if(!error && response.statusCode == 200) {
//load xml returned from GET to url
var cik_xml = cheerio.load(xml)
console.log('i = ' + i);
//map company ticker symbol to cik value scraped from xml
TickerToCIK[companyTickerList[i]] = cik_xml('company-info cik').text();
console.log('TICKER = ' + companyTickerList[i] + ' CIK = ' + cik_xml('company-info cik').text());
}
}
}(i)
}
I haven't tested the above, but you can see how I wrapped the request in a function, and passed that function the iterator value as an argument.

Related

Passing variables within the functions : I want to pass mentioned variable (insTypeDB) to another function. Please see the image

Passing variables within the functions : I want to pass mentioned variable (insTypeDB) to another function. Please see the image.
//Getting Symbol details from DB API
var insTypeDB;
pm.sendRequest("http://192.168.14.116:8080/ords/unidata/symbol/symbol/" + dataArr[1], function (err, response) {
var resBoday = response.json()
insTypeDB = resBoday.items[0].instrument_type_id;
//var intInsTypeDB = parseInt(insTypeDB);
console.log("insTypeDB " + insTypeDB);
//pm.expect(insTypeDB).is.to.equals(2);
});
//Verify Instrument Type with DB API
pm.test("Row : " + i + " - " + dataArr[1] + " : Verify symbol Instrument type with DB", function () {
let insTypeRes = dataArr[2];
let intInsType = parseInt(insTypeRes);
console.log("insType " + intInsType);
pm.expect(insTypeDB).is.to.equals(intInsType);
});[enter image description here][1]
Passing Variables error
//Getting Symbol details from DB API
var insTypeDB;
pm.sendRequest("http://192.168.14.116:8080/ords/unidata/symbol/symbol/" + dataArr[1], function (err, response) {
var resBoday = response.json()
insTypeDB = resBoday.items[0].instrument_type_id;
//var intInsTypeDB = parseInt(insTypeDB);
console.log("insTypeDB " + insTypeDB);
//pm.expect(insTypeDB).is.to.equals(2);
//Verify Instrument Type with DB API
pm.test("Row : " + i + " - " + dataArr[1] + " : Verify symbol Instrument type with DB", function () {
let insTypeRes = dataArr[2];
let intInsType = parseInt(insTypeRes);
console.log("insType " + intInsType);
pm.expect(insTypeDB).is.to.equals(intInsType);
});[enter image description here][1]
});
add the test inside the sendRequest as it is a call back else use setTimeOut which will wait for the value to be populated
pm.sendRequest("http://192.168.14.116:8080/ords/unidata/symbol/symbol/" + dataArr[1], function (err, response) {
var resBoday = response.json()
insTypeDB = resBoday.items[0].instrument_type_id;
//var intInsTypeDB = parseInt(insTypeDB);
console.log("insTypeDB " + insTypeDB);
pm.varaible.set("insTypeDB",insTypeDB);
});
setTimeout(()=>{
pm.test("Row : " + i + " - " + dataArr[1] + " : Verify symbol Instrument type with DB", function () {
let insTypeRes = dataArr[2];
let intInsType = parseInt(insTypeRes);
console.log("insType " + intInsType);
pm.expect(pm.varaible.get("insTypeDB")).is.to.equals(intInsType);
})
},5000)

Inserting an element in a specific id based on a data attribute

I am trying to dynamically insert elements within a loop, in to the corresponding DIVs based on the dataset values. Basically if the two elements have matching dataset value, it should be inserted in to a specific div.
The dataset values are unique, however in some cases the dataset values can appear more than once.
I have used the following code in another part of the project I'm working on, however I can't seem to make it work with the next thing I need to do.
var callingPointsWrapper = document.querySelectorAll(".callingstations");
var currentCallingWrapper = [...callingPointsWrapper].find((wrapper) => wrapper.dataset.callingpointsid === trainUID);
var callingWrapperFragment = document.createRange().createContextualFragment(callingPointsTemplate);
// add to correct element
callingPointsWrapper.appendChild(callingPointsTemplate);
All my code is shown below in context. Thanks in advance.
// scripts
// change protocol to https if http
if (window.location.protocol != 'https:') window.location.protocol = 'https';
//
var info = document.querySelector(".info");
// check if geolocation works/is supported using if statement
// if geolocation is supported
if ("geolocation" in navigator) {
// log to console
console.log("GeoLocation is working.");
// function to run if geolocation is supported
navigator.geolocation.getCurrentPosition(function(position) {
// store users coords
var lat = position.coords.latitude;
var lon = position.coords.longitude;
// log them to console
console.log("Your coordinates are: " + lat + "," + lon);
// callback function to use users coordinates in another function
findNearestStation(lat, lon);
});
// if geolocation is not supported
} else {
// log to console
console.log("GeoLocation is not supported.");
}
// empty array for timetable information
var serviceUrlArray = [];
function findNearestStation(lat, lon) {
// log to console
// console.log("Your coordinates are: " + lat + "," + lon);
// api keys and tokens
var appID = "xxx";
var appKey = "xxxxxx";
// api for nearest stations url template
var transportApiUrl = "https://transportapi.com/v3/uk/train/stations/near.json?app_id=" + appID + "&app_key=" + appKey + "&lat=" + lat + "&lon=" + lon + "&rpp=5";
// ajax request to get nearest stations
var nearbyStationsReq = new XMLHttpRequest();
nearbyStationsReq.open('GET', transportApiUrl, true);
nearbyStationsReq.onload = function() {
// results window
var resultsWindow = document.querySelector(".results-window");
// empty array for the timetable urls
var timetableUrlArray = [];
// empty array for station codes
var stationCodeArray = [];
// clear the results window
resultsWindow.innerHTML = "";
if (this.status >= 200 && this.status < 400) {
// response data
var res = JSON.parse(this.response);
// variable for stations array in response
var data = res.stations;
// for loop to iterate through response data
for (var i = 0; i < data.length; i++) {
// get information from response data
var code = data[i].station_code;
var name = data[i].name;
var distanceMetres = data[i].distance;
var distanceKilometres = (distanceMetres / 1000).toFixed(1);
var distanceKilometres = distanceKilometres + "km";
// log data to console to reference
// console.log("Code: " + code + " | Name: " + name + " | Distance: " + distanceKilometres);
// generate urls for timetable data
var timetableUrl = "https://transportapi.com/v3/uk/train/station/" + code + "/live.json?app_id=" + appID + "&app_key=" + appKey + "&darwin=true&train_status=passenger";
// push completed urls to the array
timetableUrlArray.push(timetableUrl);
// push codes to empty array
stationCodeArray.push(code);
// template for nearest stations result container
var resultTemplate =
"<div class='result'>" +
"<div class='station-name'>" +
"<span class='service-origin'>" +
"<span class='nr-logo'>" +
"<img src='assets/images/nr.svg' alt='National Rail Logo'></span>" + name + "</span>" +
"</div>" +
"<div class='service-results-wrapper' data-stationcode='" + code + "'></div>" +
"</div>";
// insert template in to the results window
resultsWindow.innerHTML += resultTemplate;
}
// log to console
// console.log(stationCodeArray)
// for loop to create a request for each station
for (var i = 0; i < timetableUrlArray.length; i++) {
// ajax request for timetable request
var timetableReq = new XMLHttpRequest();
timetableReq.open('GET', timetableUrlArray[i], true);
timetableReq.onload = function() {
if (this.status >= 200 && this.status < 400) {
// response from request
var res = JSON.parse(this.response);
// data for timetable info
var data = res.departures.all;
// declare service results wrapper
var serviceResultsWrapper = document.querySelectorAll(".service-results-wrapper");
// loop to go through the data
for (var i = 0; i < data.length; i++) {
// information required
var currentStation = res.station_name;
var currentStationCode = res.station_code;
var aimedDepartTime = data[i].aimed_departure_time;
var expectedDepartTime = data[i].expected_departure_time;
var destination = data[i].destination_name;
var platform = data[i].platform;
var operator = data[i].operator_name;
var status = data[i].status;
var trainUID = data[i].train_uid;
// generate url
var serviceURL = "https://transportapi.com/v3/uk/train/service/train_uid:" + trainUID + "///timetable.json?app_id=" + appID + "&app_key=" + appKey + "&darwin=true&live=true"
// log data to console
console.log("Current Station: " + currentStation + " | Current Station Code: " + currentStationCode + " | Aimed: " + aimedDepartTime + " | Expected: " + expectedDepartTime + " | Destination: " + destination + " | Platform: " + platform + " | Status: " + status + " | Operator: " + operator + " | ID: " + trainUID + " | URL: " + serviceURL);
// if platform is null
if (platform === null) {
// change variable to string
var platform = "n/a";
}
// switch statement to change styling based on status
switch (status) {
case "EARLY":
var status = '<span class="status ontime">On time</span>';
break;
case "ON TIME":
var status = '<span class="status ontime">On time</span>';
break;
case "LATE":
var status = '<span class="status delayed">Delayed' + " " + expectedDepartTime + '</span>';
var aimedDepartTime = '<span class="time unavailable strikethrough">' + aimedDepartTime + '</span>';
break;
case "CANCELLED":
var status = '<span class="status cancelled">Cancelled</span>';
break;
case "NO REPORT":
var status = '<span class="status unavailable">Unavailable</span>';
break;
case "STARTS HERE":
var status = '<span class="status ontime">On time</span>';
break;
case "OFF ROUTE":
var status = '<span class="status unavailable">Unavailable</span>';
break;
case "CHANGE OF ORIGIN":
var status = '<span class="status unavailable">Unavailable</span>';
break;
default:
var status = '<span class="status unavailable">Unavailable</span>';
}
// template for service boxes
var serviceBoxTemplate = "<span class='service-box' data-station='" + currentStationCode + "' data-uid='" + trainUID + "'><span class='service-time-status'><span class='service-depart-time'>" + aimedDepartTime + "</span>" +
status +
"<span class='service-depart-platform'>Plat. <span class='service-platform-number'>" + platform + "</span></span></span>" +
"<span class='service-destination'><span class='service-destination-name'>" + destination + "</span></span>" +
"<span class='callingstations' data-callingpointsid='" + trainUID + "'>Leigh-on-Sea, Chalkwell, Westcliff, Southend Central, Southend East, Thorpe Bay, Shoeburyness</span>" +
"<span class='service-operator'>Operated by <span class='service-operator-by'>" + operator + "</span></div>";
// inserts correct service in to correct station element based on matching codes
var currentWrapper = [...serviceResultsWrapper].find((wrapper) => wrapper.dataset.stationcode === currentStationCode);
var serviceBoxFragment = document.createRange().createContextualFragment(serviceBoxTemplate);
// add to correct element
currentWrapper.appendChild(serviceBoxFragment);
// ajax request to get service info
var serviceReq = new XMLHttpRequest();
serviceReq.open('GET', serviceURL, true);
serviceReq.onload = function() {
if (this.status >= 200 && this.status < 400) {
// response text
var res = JSON.parse(this.response);
// get array within response text
var data = res.stops;
// get the trains UID
var trainUID = res.train_uid;
// var currentStation = res.station_name;
// new array for calling points
var callingPointsArray = [];
for (var i = 0; i < data.length; i++) {
// get the calling points station names
var callingPoint = data[i].station_name;
// push names in to an array
callingPointsArray.push(callingPoint);
// create a string and add a comma between each name
var callingPointStr = callingPointsArray.join(", ");
// split the array where the calling
var subsequentCallingPoints = callingPointStr.split(currentStation);
var callingPointsTemplate = "<span>" + subsequentCallingPoints + "</span>";
subsequentCallingPoints[1].substring(1).trim()
}
var callingPointsWrapper = document.querySelectorAll(".callingstations");
var currentCallingWrapper = [...callingPointsWrapper].find((wrapper) => wrapper.dataset.callingpointsid === trainUID);
var callingWrapperFragment = document.createRange().createContextualFragment(callingPointsTemplate);
// add to correct element
callingPointsWrapper.appendChild(callingPointsTemplate);
// // add to correct element
// currentWrapper.appendChild(callingPointsFragment);
// callingPointsWrapper[0].innerHTML = "";
// callingPointsWrapper[0].innerHTML = subsequentCallingPoints[1].substring(1).trim();
// console.log(callingPointsArray)
} else {
// We reached our target server, but it returned an error
}
};
serviceReq.onerror = function() {
// There was a connection error of some sort
};
serviceReq.send();
}
// console.log(serviceUrlArray)
} else {
// We reached our target server, but it returned an error
}
};
timetableReq.onerror = function() {
// There was a connection error of some sort
};
timetableReq.send();
}
} else {
// log to console
console.log("There is an error.");
}
};
nearbyStationsReq.onerror = function() {
// log to console
console.log("There is an error.");
};
nearbyStationsReq.send();
}
// var request = new XMLHttpRequest();
// request.open('GET', '/my/url', true);
// request.onload = function() {
// if (this.status >= 200 && this.status < 400) {
// // Success!
// var data = JSON.parse(this.response);
// } else {
// // We reached our target server, but it returned an error
// }
// };
// request.onerror = function() {
// // There was a connection error of some sort
// };
// request.send();
// x

getting XMLHttpRequest cannot load (URL) Response for preflight is invalid (redirect)

here am trying to get reccurring events from calendar list for sharepoint Online app and there am using code as like
hostWebUrl = decodeURIComponent(manageQueryStringParameter('SPHostUrl'));
function GetListData() {
var webUrl = hostWebUrl;// = "http://server/sitewhereyourlistexists";
var listGuid = "{2000da75-8663-42d9-9999-ad855c54b4e0}"
// An XMLHttpRequest object is used to access the web service
var xhr = new XMLHttpRequest();
var url = webUrl + "/_vti_bin/Lists.asmx";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xhr.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/sharepoint/soap/GetListItems");
// The message body consists of an XML document
// with SOAP elements corresponding to the GetListItems method parameters
// i.e. listName, query, and queryOptions
var data = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<soap:Body>" +
"<GetListItems xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\">" +
"<listName>" + listGuid + "</listName>" +
"<query>" +
"<Query><Where>" +
"<DateRangesOverlap>" +
"<FieldRef Name=\"EventDate\"/>" +
"<FieldRef Name=\"EndDate\"/>" +
"<FieldRef Name=\"RecurrenceID\"/>" +
"<Value Type=\"DateTime\"><Today/></Value>" +
"</DateRangesOverlap>" +
"</Where></Query>" +
"</query>" +
"<queryOptions>" +
"<QueryOptions>" +
"<ExpandRecurrence>TRUE</ExpandRecurrence>" +
"</QueryOptions>" +
"</queryOptions>" +
"</GetListItems>" +
"</soap:Body>" +
"</soap:Envelope>";
// Here we define what code we want to run upon successfully getting the results
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var doc = xhr.responseXML;
// grab all the "row" elements from the XML results
var rows = doc.getElementsByTagName("z:row");
var results = "Today's Schedule (" + rows.length + "):\n\n";
var events = {};
for (var i = 0, len = rows.length; i < len; i++) {
var id = rows[i].getAttribute("ows_FSObjType"); // prevent duplicates from appearing in results
if (!events[id]) {
events[id] = true;
var allDay = rows[i].getAttribute("ows_fAllDayEvent"),
title = rows[i].getAttribute("ows_Title"),
start = rows[i].getAttribute("ows_EventDate");
var index = start.indexOf(" ");
var date = start.substring(5, index) + "-" + start.substring(2, 4); // get the date in MM-dd-yyyy format
start = start.substring(index, index + 6); // get the start time in hh:mm format
var end = rows[i].getAttribute("ows_EndDate");
index = end.indexOf(" "); end = end.substring(index, index + 6); // get the end time in hh:mm format
results += date + " " + (allDay == "1" ? "All Day\t" : start + " to " + end) + " \t " + title + "\n";
}
}
alert(results);
} else {
alert("Error " + xhr.status);
}
}
};
// Finally, we actually kick off the query
xhr.send(data);
}
after calling this function in decument. ready section it is not retrieving any data but there is ine error which i can see in console of browser that is as below
You will click on the correct request in the left hand side panel, then select "Inspectors" in the right hand side top panel. Then choose between the different request and response options.

How can access the data recieved from API outside of this function

I have used node.js and request.js to access form information from our email services API. With the console.log in the function I am able to see all the info that I need. I have tried to access it outside of the function with dot notation(request.missionStatement) which I don't think is right. I want to be able to display this on a page within an express.js app.
var request = require('request');
// Basic Authentication credentials
var username = "user";
var password = "password";
var authenticationHeader = "Basic " + new Buffer(username + ":" + password).toString("base64");
// Search for Custom Data Objects Affiliate Falculty form
request(
{
url : "url to api",
headers : { "Authorization" : authenticationHeader }
},
function (error, response, body) {
var parsedData = JSON.parse(body);//convert text from API to JSON file
var missionStatement = [];
for (var i = 0; i < parsedData.elements.length ; i++) {
var individualStatement = "";
//Get text submission from form and push into array
individualStatement += (parsedData.elements[i].fieldValues[4].value + ", " + parsedData.elements[i].fieldValues[2].value + " " + parsedData.elements[i].fieldValues[3].value + ", " + parsedData.elements[i].fieldValues[0].value);
missionStatement.push(individualStatement);
};
console.log(missionStatement)
}
);
The variable missionStatement is a local variable declared inside an anonymous function passed as an argument to the request function, and thus it is inaccessible once the anonymous function returns. You must save your result elsewhere. Try something like this:
var request = require('request');
// Basic Authentication credentials
var username = "user";
var password = "password";
var authenticationHeader = "Basic " + new Buffer(username + ":" + password).toString("base64");
var result;
// Search for Custom Data Objects Affiliate Falculty form
request(
{
url : "url to api",
headers : { "Authorization" : authenticationHeader }
},
function (error, response, body) {
var parsedData = JSON.parse(body);//convert text from API to JSON file
var missionStatement = [];
for (var i = 0; i < parsedData.elements.length ; i++) {
var individualStatement = "";
//Get text submission from form and push into array
individualStatement += (parsedData.elements[i].fieldValues[4].value + ", " + parsedData.elements[i].fieldValues[2].value + " " + parsedData.elements[i].fieldValues[3].value + ", " + parsedData.elements[i].fieldValues[0].value);
missionStatement.push(individualStatement);
};
result = missionStatement;
displayResult();
});
function displayResult() {
console.log(result);
}
Your missionStatement will now be saved in result, but only after the anonymous callback to request() has been called (when the actual request is finished).

XMLHttpRequest calls not finishing before return statement so undefined

I'm attempting to count how many items total are in the database I'm querying. It's third party so it's cross domain XMLHttpRequests but I'm making the method in a Chrome Extension and the permissions bit in the manifest.json let's it work nicely.
The problem I seem to be having is this: I'm looping through a list of categories and counting the amount in each before the XMLHttpRequests are coming back from the external server. The methods are started by the press of a button of id="countButton". Here's the relevant javascript/jQuery:
//simple listener for the button
document.getElementById('countButton').addEventListener('click', function() runTotalCount()}, true);
//loops through a list of categories in a drop down with values 0-36
function runTotalCount(){
var sum = 0;
$('#categorySelect option').each(function(){
var value = $(this).val();
sum += retrieveCategoryCount(value);
alert("New Sum = " + sum);
});
var total = "<p>Total items in Sum is " + sum + "</p>";
document.getElementById('results').innerHTML = total;
}
//actually makes the request and sums the items count for each category
//the server response is a json with an alphabetized "items" per category
function retrieveCategoryCount(num){
var sum = 0;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4 && xhr.status == 200){
var str = xhr.responseText;
alert("str = " + str);
var json = $.parseJSON(str);
alert("JSON = " + json);
for(item in json.alpha){
alert("items count = " + json.alpha[item].items);
sum += json.alpha[item].items;
}
alert("Category Sum = " + sum);
return sum;
}
}
xhr.open(
"GET",
"http://services.runescape.com/m=itemdb_rs/api/catalogue/category.json?category=" + num,
true);
xhr.send(null);
}
As it is the stuff within the onreadystate for retrieveCategoryCount never gets called because the XMLHttpRequests are still pending by the time the function finishes. On synchronous calls the alert("Category Sum = " + sum); returns the right number but then the function return just below it is NaN (I'd rather not hang up the browser though so asynchronous is what I'd prefer for a solution).
What needs to change to properly get the item count? Thanks in advance.
UPDATE:
I've also tried code for retrieveCategoryCount of this:
function retrieveCategoryCount(num){
var sum = 0;
$.getJSON("http://services.runescape.com/m=itemdb_rs/api/catalogue/category.json?category=" + num, function(data){
for(item in data.alpha){
alert("items count = " + data.alpha[item].items);
sum += data.alpha[item].items;
}
alert("Category Sum = " + sum);
return sum;
});
}
The problem here is that the callback never gets run because the request is still pending by the time the value returned from the function is added to "sum".
You can put the code that should happen AFTER the async call completes into a callback function and pass that into your async function, then have it callback.
var sum = 0,
setTotalCount = function(data){
.. stuff to set the dom element based on callback
};
$('#categorySelect option').each(function(){
var value = $(this).val();
retrieveCategoryCount(value, setTotalCount);
});
function retrieveCategoryCount(num, callback){
var sum = 0;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4 && xhr.status == 200){
var str = xhr.responseText;
alert("str = " + str);
var json = $.parseJSON(str);
alert("JSON = " + json);
for(item in json.alpha){
alert("items count = " + json.alpha[item].items);
sum += json.alpha[item].items;
}
alert("Category Sum = " + sum);
callback(sum); // callback the function you passed in
}
}
xhr.open(
"GET",
"http://services.runescape.com/m=itemdb_rs/api/catalogue/category.json?category=" + num,
true);
xhr.send(null);
}
The callback function you pass to onreadystatechange is not retrieveCategoryCount. It's return value is lost because the function is only called in response to the readystatechange event.
Do what you need to do with the data in the callback. Don't try to return the data.

Categories