In this app I’m fetching as rss feed as JSON data to display. I want to add each title to an Observable so I can slice through the strings and display them differently.
However, for some reason it doesn’t allow me to add the titles to my Observable:
var data = Observable();
var titles = Observable();
function getScores(){
fetch('https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=100&q=https://twitrss.me/twitter_user_to_rss/?user=simplenbascores')
.then(function(response) { return response.json(); })
.then(function(responseObject) {
data.value = responseObject;
for(var i = 0; i < responseObject.responseData.feed.entries.length; i++){
var entry = responseObject.responseData.feed.entries[i];
titles.add(entry.title);
//console.log(entry.title);
} });
}
When checking titles.length
it is 0.
Any ideas why the titles aren’t being added?
Try logging each entry if nothing logs its because the array is empty, and if you want get rid of the for loop and use forEach:
responseObject.responseData.feed.entries.forEach(entry) {
titles.add(entry.title);
});
Or I believe you can just:
titles = Observable(responseObject.responseData.feed.entries);
If that doesn’t work try:
titles = Observable(responseObject.responseData.feed.entries).expand();
tried all three ways and the list is still empty
None will work if the array is empty, I was just shortening the code regardless, you have to figure out why the response from the server is sending you back an empty array.
It’s not an empty array as I can display the titles in my UX and with console.log(entry.title);
When do you check for titles.length
and make sure nothing else is altering the observable. You’re not calling titles.clear()
anywhere right?
after the function:
function getScores(){
fetch('https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=100&q=https://twitrss.me/twitter_user_to_rss/?user=simplenbascores')
.then(function(response) { return response.json(); })
.then(function(responseObject) {
data.value = responseObject;
for(var i = 0; i < responseObject.responseData.feed.entries.length; i++){
var entry = responseObject.responseData.feed.entries[i];
//console.log(entry);
//titles.push(entry.title);
console.log(entry.title);
}
});
}
getScores();
console.log(titles.length);
(obviously without the comments)
titles.length
will be empty there, since getScore is an async promise.
How could I get each title in an array then?
I think you’re looking for the add
function for Observable
's, not push
titles.add
is correct, and the titles are in the array, but not when you check for them. A bit after.
Yes, what Bjørn is saying is also correct; you first set up a callback and then print the Observable
's length
, and sometime later that callback gets called and populates the Observable
. Logging inside your callback, after your for
loop would work:
.then(function(responseObject) {
data.value = responseObject;
for(var i = 0; i < responseObject.responseData.feed.entries.length; i++){
var entry = responseObject.responseData.feed.entries[i];
//console.log(entry);
titles.add(entry.title);
//console.log(entry.title);
}
console.log(titles.length);
});
Yeah Jake I’ve tried .add
the .push
is from where i tried a normal js array, same result. Okay thanks Bjorn, what should I do so they stay there after the promise?
right so I’ve just done that but still not sure how I can make the Observable keep the list after the function?
They are there “after” the promise, but not in the lines below, because of the way JS event loop works. Either tell me/us what you want to achieve, and we can help you, or try to read up on async programming.
You do keep the contents its just delayed, when you check for its length after the for loop you get 0 because you’re synchronously checking its length, but if you bind it to an <Each>
in UX you’ll be able to see that it actually has the titles, depending on what you want to do afterwards with the data, you might just have to use Promises.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Okay haha, I’ll do both. I want to add all the titles to an array/list so I can iterate throught them later and edit the strings so I can display them differently.
It’s not that the Observable
or array
loses its values, it’s that the code that populates the list runs asynchronously, so even though it’s written in the scope of the function, it actually gets executed a bit later (whenever the http request comes back with some data).
I think I understand now. But I’m still unsure as when to access my titles observable when it is populated?
Can you describe more in detail what you’d like to do with this data? Putting them in an array to edit/display them later sounds like it’ll cause more problems than it’ll solve.
Observable
's aren’t just containers the UI can see into, they also propagate values forward to the UI. For example, if you databind the UI to a specific Observable
, then add
value to that same Observable
, that change will get propagated to the UI and it will change automatically.
Generally you’ll want to leverage this when displaying data. It’s likely your use case can be covered with a combination of Observable
and its map
function and databinding, which is going to be a much nicer way to do things than the old imperative way of “making a list, changing the list, and force-feeding it to the UI somehow”