var songs = [];
request.get(getSongs, function(error, response, body){
append(songs,body);
});
function append(arr, data){
for (let j = 0; j < data.items.length; j++) {
console.log(data.items[j].track.name);
arr.push(songs,data.items[j].track.name);
}
}
console.log(songs); //outputs '[]'
I've google a lot and I'm not sure what I'm doing wrong.
For some context, request.get() returns between 1 and 20 objects, and I'd like to add an attribute (or more) of all of them to the array 'songs'. They console.log() correctly and their positions are correct, but when I log the array, it appears to be empty.
What am I doing wrong? Thanks for the help.
The issue you have here is that you're logging the array synchronously. Currently, your program currently runs as follows:
Defines an empty array
Kicks off a request to get songs
Defines your append function
logs the empty array
Gets back the songs
Populates the array with the songs.
If you console.log after your append call you'll see you have all the songs in your array.
Related
I'm trying to write a function to append an array with a for loop. The data I'm trying to append is in a JSON repsonse. However, I keep getting x10 Array[] in the web console instead of one array with all the data. When I run console.log(dates[0]) I get returned in the web console "undefined". This tells me the data isn't even making it into the array. When I run console.log(time) I return x10 peices of data from the JSON I want but of course its not in the array. Any ideas? Thanks.
function mostRecent(time) {
var dates=[];
for (var i = 0; i < time.length; i++) {
dates.push(dates[i]);
}
return console.log(dates);
}
You are pushing dates[i] with every loop cycle. And since dates array keeps being empty, you are actually pushing undefined.
Just replace dates.push(dates[i]) with dates.push(time[i]).
Note: You should return dates instead of console.log.
so I have a node js / websocket server going, where I want to store multiple instances of setInterval timers...
I have them stored in an array of [timer, client] objects that I want to step through when a client disconnects, then step through the array and turn off all the timers that are paired with the disconnecting client before removing them from the array.
Removing the objects connected with the clients is working, however, the timers are not stopping...
I am declaring the timers like this -
clientSchedulePairs.push([setInterval(makeVisibleHandler, master_period, item, name), client]);
then trying to turn the schedule off like this when a client disconnects-
clearInterval(clientSchedulePairs[i][0]);
in my research i found this question -
clearInterval() is not stopping setInterval() - Firefox Extension Development
which says that I need to make a timer a global variable? but that isnt helping because if I have multiple timers for multiple clients how can i make them global variables?
I am storing them in a global const array that is declared globally such as-
const clientSchedulePairs = [];
however it is not working...
any idea on if the reason its not working is because its not declared as a global variable? or how I can get around this and get it to work? (i already tried declaring the schedule as a variable in my method before adding it to the array)
thanks.
UPDATED---
i got it working turning off the timers --- not sure if it had something to do with the way the client was disconnecting, after I removed my for loop into an external method that took in the client socket as a variable, then looped through my array of client / timer pairs and checked for the clients and removed them it started working. However, I am running into a kind of strange issue now...
as i said, i am looping through a clientTimerPairs array and checking if the client paired to that timer is === to the client_socket that was passed in from when the method was called when a client disconnects, in this loop, calls this--
clearInterval(clientTimerPairs[i].interval);
and the timers turn off, however I had a problem removing the client - timer tuples from the clientTimerPairs array now
i couldnt get them to remove from the array, so i changed it to work like this-
var indexToRemove = [];
for (var i = 0; i < clientTimerPairs.length; i++) {
if (clientTimerPairs[i].pairedClient === client_socket) {
clearInterval(clientTimerPairs[i].interval);
indexToRemove.push(i);
}
}
for (var i = 0; i < indexToRemove.length; i++) {
console.log('removing index ' + indexToRemove[i] + '...');
clientSchedulePairs.splice(indexToRemove[i], 1);
}
however, even if i console print indexToRemove, and it has all index 0 - 6 in it, (because during testing i only connected 1 client with 6 timers), it should be stepping through clientTimerPairs and removing every single index so clientTimerPairs is empty, however, for some strange reason instead of going from 6 to 0 size, the array always ends up at 3 size!
even though it prints the removing index line 6 times and says it is removing index 0 - 5, 3 items are always left over in the clientTimerPairs array!
any idea why this might happen?
That push statement does not provide a proper key-value pair. How about using es6 Map to secure actual pairs?
However, it should work as intended.
const timers = [];
for (let i = 0; i < 5; i++) {
timers.push([setInterval(runTimer.bind({ id: i}), 100), i]);
}
function runTimer() {
console.log(`running for id ${this.id}`);
}
setTimeout(() => {
console.log('clearing timers')
for (let i = 0; i < timers.length; i++) {
clearInterval(timers[i][0]);
}
}, 2000);
Edit regarding the addition to your post
The splicing does exactly as it is intended to do. Say you have an array of 6 elements. You are clearing elements from the array using an array of indices and remove the first element. That array length becomes 5. The second index points to the 6th element. When you try to splice the 6th element by its index, nothing happends. This is because you removed one element from the array, which made the 6th element shift to the 5th position.
A simple solution could be using es6 filter:
let items = ['one', 'two', 'three', 'four'];
let indices = [1, 3];
items = items.filter((item, index) => indices.indexOf(index) === -1);
This returns an array with the first and third elements.
I have a rest.get request inside a for loop, that is sending around 20 queries (based on data from a previous request that changes the query each time). My problem is that it seems to be running the for loop completely through and then the queries run asynchronously and are responding with the data that returns the quickest instead of consecutively. If I console.log the index of the forloop inside the .end function, it is undefined until the forloop is finished and then it is the final number (even though it is all inside the for loop). I am trying to save (push to an array) the data in the same order I am sending the request, so I can match the data with the previous get response list that I’m printing out. Is there a way to assign my response data to an array in the order that I am sending the request instead of first come first serve?
// this function is being called inside the previous query
function carData(req, res) {
var carNameJson = [];
var resultToJson = [];
//singleCars.length is defined in a previous query and is an array of car IDs
for (var index = 0; index < singleCars.length; ++index) {
//Grab each individual car ID and concatinate it into a Query
var carNames = singleCars[index];
var carQuery = "https://queryinfo";
var finalSingleQuery = "carQuery + carNames";
// puts the data into an array of JSON objects
carNameJson = {
carID: carNames
};
// result is a global variable assigned as an empty array
// it list all the car IDs in a JSON format
result.push(carNameJson);
rest
.get(finalSingleQuery)
.proxy("http://proxyinfo")
.end(function(resp) {
resultToJson = {
carInfo: resp.body
};
// resultInfo is a global variable assigned as an empty array
resultInfo.push(resultToJson);
return resultToJson;
});
}
}
This code all works, but it gives me the data out of order, so I can't match the car information to the list of car IDs. I am new to node, so I may be doing this all wrong. Any help would be appreciated!
You could use the index variable to target where to store the response. For that you must make sure the index variable is local to the for body, which you can achieve with let (instead of var):
for (let index = 0; index < singleCars.length; ++index) {
// ...
// store directly at the correct index:
resultInfo[index] = resultToJson;
You might also be interested to know when you have all results. This you can do with this condition, just after the assignment to resultInfo[index]:
if (resultInfo.filter(Object).length === singleCars.length) {
// maybe call a callback here.
}
You're performing restful response inside of a for loop. Instead, consider building a complete JSON object filled with all the data the client will need (in other words, send it all as 1 big response, instead of lots of little responses).
Use the for loop to build the JSON, then outside of the loop, perform your 1-time restful response.
That way you don't have to worry about the data coming through out of order, and the response is complete and not missing important information like index.
I am working on dynamically generating XML for printing labels. I have an array of values generated with map, the format of this array should end up as such:
[[val1a, val1b, val1c],[val2a,val2b,val2c],[val3a,val3b,val3c]]
I am unable to log to the browser console in this application, so must use provided logging APIs to view the actual values of the array at any given point. The format presented by logging is as such:
val1a,val1b,val1c,val2a...
The values are generated like so:
for(var i = 0; i < lines; i++) {
for(var j = 0; j < quantity; j++){
smCnts.push([i]);
}
}
Where i is the line number of the specific "record", and j is iterating over the quantity, pushing the line number to the array smCnts. Resulting in a dataset like this (assuming line 1 has a quantity of 3, and line 2 has a quantity of 2 etc.):
[[1], [1], [1], [2], [2], [3]]
This array is then mapped using a function that gets values from the lines:
var smLbls = smCnts.map(getData);
Resulting in something like the first array listed in this question.
The problem results when trying to index the array for a specific value:
var foo = smLbls[1];
This returns nothing, I don't even know if it returns null as the logging api returns only: .
However, logging smLbls returns the first mentioned array as described in the second code snippet. What would be causing this issue? I need to be able to get the index of the index of an array like so:
var bar = smLbls[1][3];
Everything else is working as expected, I am just unable to access this data for whatever reason, maybe I am not understanding JavaScript fully?
I am unable to log to the browser console in this application, so must use provided logging APIs to view the actual values of the array at any given point. The format presented by logging is as such:
My advice, use the logs to extract a snapshot of your data:
nlapiLogExecution('debug', 'sample', JSON.stringify(data));
...and work in the browser.
I am working on a JavaScript web app that takes input from a user (the name of a musical artist) and outputs a list of related artists and their most popular song, as determined by the Spotify API. I initially had a rudimentary version of this functioning, but it would just post a list of all the related artists with a list of those related artists' most popular songs immediately above it, and I want the entire object to print out (artist plus most popular song).
I have a series of objects representing the artists that I received through the spotify-web-api-js node module with Node.js and Browserify to make it function on the browser, uniquely identified by their Spotify ID. How can I loop through them if I don't know those IDs in advance before a user does a search so that I can properly push them into an object that I can then input to the DOM through jQuery's append? I've been trying to access them in various ways, but it doesn't seem to be working:
s.getArtistRelatedArtists(originalArtistId, function(err, data) {
for (i = 0; i < data.artists.length; i++)
{
console.log(data.artists[i].name);
relatedArtistsObject[data.artists[i].id] = {
name: data.artists[i].name,
songs: []
};
s.getArtistTopTracks(data.artists[i].id, "US", function (err, data2) {
if (relatedArtistsObject[data2.tracks[0].artists[0].id] !== undefined)
{
// console.log(data2.tracks[0].name); -- this outputs the song titles I want
relatedArtistsObject[data2.tracks[0].artists[0].id].songs.push(data2.tracks[0].name);
}
});
}
console.log(relatedArtistsObject);
// loop through this object and print it through the screen
for (k = 0; k < relatedArtistsObject.length; k++)
{
console.log(relatedArtistsObject.id.songs[0].name);
$('#related-artist').append(relatedArtistsObject[k]);
}
// $('#related-artist').append(relatedArtistsObject);
});
Here is a link to the full code (not functioning because it doesn't have Node.js/browserify enabled): https://jsfiddle.net/pmh04e99/
This answer is partially helpful, but doesn't apply here because the JSON output doesn't have a "name" field in the array I want to access. Instead, songs is an array of 1, and the content I want is within item 0. My console.log output of the relatedArtistsObject looks like this, for example:
How can I access these objects in the DOM through my code when I don't know the spotify IDs right now?
Note: I'm aware that i'm not error handling yet, but I want to be able to implement the main functionality first.
You can use for in or use Object.keys.
The former will iterate over each enumerable property name of the object, and setting that name into the specified variable. You can then use that name to access that object's property value.
The latter will return an array of the object's property names. You can then use a regular for loop to iterate over that array and use each of the values in the array as the id
For...In
for(id in relatedArtistsObject){
var artist = relatedArtistsObject[id];
console.log(artist.name,artist.songs);
}
Object.keys
var ids = Object.keys(relatedArtistsObject);
for(var i=0; i<ids.length; i++){
var artist = relatedArtistsObject[ids[i]];
console.log(artist.name,artist.songs);
}