I'm trying to perform the following actions at a high level:
Make an API call to generate an array of cardIDs for a Trello board
Iterate and make an API call for each cardID, pull some action (history) data for each card and store that in the action_tableData table
Once complete, append action_tableData to the table object
The way I understand things is that I need to perform a getJSON call, let that finish and then perform another getJSON on top of that. I've looked around and understand the $.when() function might help, but I can't seem to even remotely make that work.
I think there could be an issue when the getJSON returns an undefined object, but I'm not sure how to skip those. Any help would be most appreciated!
cardIDapiCall = "https://api.trello.com/1/boards/" + boardID + "/cards?fields=id&key=" + appKey + "&token=" + tokenKey;
$.getJSON(cardIDapiCall, function(cardID) {
var cardID_tableData = [];
// Iterate over the JSON object
for (var i = 0, len = cardID.length; i < len; i++) {
cardID_tableData.push({
"card_id": cardID[i].id,
});
}
//get action data
for (var j = 1, len = cardID_tableData.length; j < len; j++) {
//this alert works
alert("card id: " + cardID_tableData[j].card_id);
var actionapiCall = "https://api.trello.com/1/cards/" + cardID_tableData[j].card_id + "/actions?key=" + appKey + "&token=" + tokenKey;
//why isn't this getting called???
$.getJSON(actionapiCall, function() {
//this alert doesn't work
alert("action call successful");
});
var action_tableData = [];
action_tableData.push({
"action_id": action[j].id,
"action_type": action[j].type,
})
table.appendRows(action_tableData);
doneCallback();
}
});
Related
I have two functions that I am trying to run when I load the page. dataRetrieve() gets the data from a firebase collection. populate() is supposed to populate a boxlist with the entries retrieved from dataRetrieve(). The main problem is that it lists the array as empty when I run populate() after dataRetrieve() no matter what I try. The last thing I tried was this:
async function dataRetrieve(){
const getAdmins = firebase.functions().httpsCallable('getAdmins');
// Passing params to data object in Cloud functinon
getAdmins({}).then((results) => {
admins = results;
console.log("admins retrieved");
console.log(admins);
}).then(() => {
populate();
});
}
async function populate(){
let list = document.getElementById("user-list");
//loop through users in out Users object and add them to the list
for (var i = 0; i < admins.length; i++) {
let newItem = document.createElement('option');
newItem.innerHTML = admins[i].first + " " +admins[i].last;
newItem.id = admins[i].uid;
if (i == 0) {
newItem.className = "active";
}
console.log(newItem.innerHTML + " " + newItem.id)
list.appendChild(newItem);
}
updateResponse(list.firstChild);
list.size = admins.length;
console.log(document.getElementById("user-list").size)
//collect all the list items
let listItems = list.querySelectorAll('option');
//loop through the list itmes and add a click listener to each that toggles the 'active' state
for (var i = 0; i < listItems.length; i ++) {
listItems[i].addEventListener('click', function(e) {
if (!e.target.classList.contains('active')) {
for (var i = 0; i < listItems.length; i ++) {
listItems[i].classList.remove('active');
}
e.target.classList.add('active');
updateResponse(e.target);
}
})
}
}
also, admins is a global variable listed at the start of the script:
var admins = [];
I am trying to run all this onload so I can instantly generate the list
I thought that .next would cause it to wait to get the values before running, but even making results a parameter and transferring it directly into the function that way gives an undefined array. I don't understand why the function insists on calling on old data. Pls help.
I'm not sure what updateResponse function does. If it's not returning a promise then I'd make the populate function synchronous first. Also do you really need to use admins array somewhere else apart from populate function that it is a global variable? If not then I'd just pass it as a parameter.
async function dataRetrieve() {
const getAdmins = firebase.functions().httpsCallable('getAdmins');
// Passing params to data object in Cloud function
const results = await getAdmins({})
console.log("admins retrieved");
console.log(results);
// Passing results in populate function
populate(results.data)
// If your function returns an array, pass the array itself
}
function populate(admins) {
let list = document.getElementById("user-list");
//loop through users in out Users object and add them to the list
// Using a for-of loop instead so no need to worry about checking the length here
for (const admin of admins) {
let newItem = document.createElement('option');
newItem.innerHTML = admin.first + " " + admin.last;
newItem.id = admin.uid;
//if (i == 0) {
// newItem.className = "active";
//}
console.log(newItem.innerHTML + " " + newItem.id)
list.appendChild(newItem);
}
updateResponse(list.firstChild);
// rest of the logic
}
I guess you know how to check when the page loads. call the retrieve function when the page is loaded. Then you should call the populate function at the end of the retrieve function. this makes sure that the populate function is called after you get all the data
I am attempting to pull information from the League of Legends API.
To simplify what I am doing, I am attempting to pull information about a user and their previous matches. The problem that I run into is that when I parse a JSON request, it returns a champion ID rather than their name (Ex: 412 rather than "Thresh").
The only solution I can see for this would be to make another JSON request and parse that data for the champion name. Currently what I have looks like this.
$.getJSON(championMasteryPHP, function (json) {
for (var i = 0; i < 20; i++) {
var champID = json[i].championId;
var championInfo = "http://example.com/champInfo.php?summonerid=" + champID;
$.getJSON(championInfo, function (json2) {
var champName = json2.name;
});
$('#champ').append("<li>"+champID+" - "+champName+"</li>")
}
});
I'm unable to access the champName variable due to it being nested within the second JSON function.
Is there a better way to do this?
$.getJSON(championMasteryPHP, function (json) {
for (var i = 0; i < 20; i++) {
var champID = json[i].championId;
var championInfo = "http://example.com/champInfo.php?summonerid=" + champID;
$.getJSON(championInfo, function (json2) {
var champName = json2.name;
$('#champ').append("<li>"+champID+" - "+champName+"</li>")
});
}
});
Just put it inside the second json request since you need to wait till that request is done anyway.
You should put the append statement in the callback because getJSON is an asynchronous method (does mean the Request is running in the background, and calls your function back when it got a response), so you should wait for the response first then you can append it to #champ :
$.getJSON(championMasteryPHP, function (json) {
for (var i = 0; i < 20; i++) {
var champID = json[i].championId;
var championInfo = "http://example.com/champInfo.php?summonerid=" + champID;
$.getJSON(championInfo, function (json2) {
var champName = json.name;
$('#champ').append("<li>"+champID+" - "+champName+"</li>")
});
}
});
Hope this helps.
I'm not loading scripts, I'm reading XML files into an array of objects.
My first [dumb] attempt was something like:
for (var i = 1; i < n; i++) {
var filePath = "xml/chapter_"+i+".xml";
$http.get( filePath ).success(function (data) {
$scope.chaptersData.push (data._chapter);
});
}
I quickly figured out this was no good, because the array will be filled in the order the files finished loading, not when they started (a race condition) and the smaller ones will finish first. I can't use the value of 'i' because of course it gets to 'n' long before any of the loading finishes.
After that I thought success(function (data, i) { would work, but it didn't. I'm out of simple ideas, and before I come up with some kind of Rube Goldberg kludge I thought I would ask the wisdom of the Internets if there is a 'right' way to do this.
You can pass i into a function which performs the request.
for (var i = 1; i < n; i++) {
getFile(i);
}
function getFile(index){
var filePath = "xml/chapter_" + index + ".xml";
$http.get( filePath ).success(function (data) {
$scope.chaptersData[index] = data._chapter;
});
}
Within the getFile function, the value of the parameter index will not change as i changes in the outer function. So it will still be at its initial value when the success function executes and can be used for populating the array.
Just get data as an object like
{
order: [] // just your chapter id or whatever identifier value in desired order
data: // whatever you're getting now
}
In your .success (which is btw depreciated and you should use .then() instead) just do
orderedChapters = [];
for (var i = 0; i < order.length; i++) {
for (var j = 0; j < data.length; i++) {
if (order[i] == data[j].id) {
orderedChapters.push(data[j]);
}
}
}
I'm a javascript newbie and has been given a problem to solve so i really need your help.
The problem is this:
I have a loop of companies list. For each company I need to make a ajax call like below.
My problem is that I want to stay in the loop and just get the value that the ajax call return so I can use that value there. Now I get the return value to the getData method. How can I solve this?
for (var j = 0; j < companiesToList.length; j = j + 1) {
getCompanyData(companiesToList[j].id, numberArray, function(data){
getData(data)
}
}
var getCompanyData = function(companyid, numbers, callback) {
var baseUrl = '../data/financial/company/';
baseUrl += companyid + '/';
numbers = numbers.distinct();
baseUrl += numbers.join(',');
tiger.ajax.core.getJSON(baseUrl, null, function(data) {
callback(data.financial);
});
};
A good way to solve this is with promises, using a library like kriskowal's Q (or any other interface that implements the promise API):
for (var j = 0; j < companiesToList.length; j = j + 1) {
getCompanyData(companiesToList[j].id, numberArray, function(data){
getData(data).then(function(result) {
// do something with result asynchronously
}
}
}
var getCompanyData = function(companyid, numbers, callback) {
// create a deferred object to return
var deferred = Q.defer();
var baseUrl = '../data/financial/company/';
baseUrl += companyid + '/';
numbers = numbers.distinct();
baseUrl += numbers.join(',');
tiger.ajax.core.getJSON(baseUrl, null, function(data) {
// resolve the promise with the retrieved data
deferred.resolve(data.financial);
});
// return the unresolved promise immediately
return deferred.promise;
};
Whether the above will work out of the box for your situation depends on what exactly you need to do inside the loop after the results come back, since if you want to be picky you aren't actually staying inside the loop, but using then as a callback (if you will) to execute code after the result is retrieved. That being said, the above pattern works well in a lot of situations like this. I can edit my answer if you provide more information about what you need to do with the data.
My code sends requests to Twitter for search data gets responses in the from of JSON. After getting the JSON, it stores the count of responses that match a certain condition in an array.
Here is the code that makes the call to the function that queries Twitter.
$(document).ready(function() {
...
graph = new HighCharts.chart({
chart: {
events: {
load: function() {
console.log("events.load");
var that = this;
var update = function() {
if (polling) {
console.log("update()");
// The least index series will be nearest the x-axis
var stackNumber = 0;
var numTweets = updateValues();
console.log(numTweets + "");
for (var i = 0, currentSeries = that.series; i < currentSeries.length; i++) {
var x = (new Date()).getTime(), // current time
y = numTweets[i];
stackNumber += y;
currentSeries[i].addPoint([x, y], true, true);
}
}
}
// set up the updating of the chart each second
var series = this.series[0];
setInterval(update, 1000);
}
}
(I'm probably missing some brace somewhere in the code-paste here, but I know for sure that my problem isn't related to a missing brace)
And here is the function that actually queries Twitter using a series of jQuery calls. The updateValues() function (which is outside the document-ready section) goes as follows:
function updateValues() {
var url = "http://search.twitter.com/search.json?callback=?&q=";
var cls = "Penn_CIS240"
var query = "%23" + cls;
var voteCount = [0,0,0,0];
// create an array of zeros
//for (var i = 0; i < 4; i++)
// voteCount.push(0);
$.getJSON(url + query, function(json){
console.log(json);
$.each(json.results, function(i, tweet) {
var user = tweet.from_user_id;
if (user % 2 == 0) {
voteCount[0] += 1;
}
else if (user % 3 == 0) {
voteCount[1] += 1;
}
else if (user % 5 == 0) {
voteCount[2] += 1;
}
else {
voteCount[3] += 1;
}
console.log("updateValues() -> getJSON -> each -> voteCount = " + voteCount);
});
console.log("updateValues() -> getJSON -> voteCount = " + voteCount);
});
console.log("updateValues() -> voteCount = " + voteCount);
return voteCount;
}
What is happening is that the variable voteCount is getting incremented properly inside the jQuery calls. However, outside of the calls, it is getting reset. So the log outputs look something like this:
updateValues() -> getJSON -> each -> voteCount = [1,0,0,0]
updateValues() -> getJSON -> voteCount = [1,0,0,0]
updateValues() -> voteCount = [0,0,0,0]
Does this problem have to do with jQuery's asynchronous calls, and I'm having interesting variable modification conflicts? Or is it something else?
When you use asynchronous callbacks in JavaScript, they execute later... asynchronously. So if you have:
var x = 5;
console.log("before getJSON", 5);
$.getJSON("/some/url", function (json) {
x = 10;
console.log("inside callback", x);
});
console.log("after getJSON", x);
the output will be
before getJSON 5
after getJSON 5
inside callback 10
Any code you want to execute after the request returns must be inside the callback; putting it physically "after" the $.getJSON call will not suffice. You should think of $.getJSON as "firing off" the JSON-getting process, then immediately returning to you; only later, when your script is done executing normal code and the server has responded, will the JavaScript event loop say "hey I got a response and am idle; time to call that callback that was waiting on the response!"
Because of this, your updateValues function will need to accept a callback of its own in order to notify its own caller that the values have been updated; just calling updateValues will only fire off the value-updating process, and the values won't be updated later until that idle time. Something like:
function updateValues(onUpdated) {
var url = "http://search.twitter.com/search.json?callback=?&q=";
var cls = "Penn_CIS240"
var query = "%23" + cls;
var voteCount = [0,0,0,0];
$.getJSON(url + query, function (json) {
// use of json to update voteCount ellided
onUpdated(voteCount);
});
}
Then calling code uses it as
updateValues(function (voteCount) {
// use the updated vote counts inside here.
});