I'm building an Angular app to show my website's articles and votes and I want to show them sorted based on their vote. I can retrieve votes making http calls, in particular:
- I have to make a http call to retrieve the list of categories and the list of their IDs (I often add categories in my website so I need to update my app)
- I have to use these IDs to make one http call for each ID to get the list of articles of that particular category.
- Every article has an ID, I have to store every ID to make another one http call for each article ID.
- Finally every n.3) response object has a 'users_vote' property. I need then to build an array to merge all the votes and then sort the array. Then I'll show the array on HTML code.
I don't understand how to chain promises so the code is just to clarify what I mean. I also know that it's really 'tricky' but I can't change anything server side at the moment and I have to deal with this.
ngOnInit() {
this.getCategories()
.then((res) => {
this.getIds(res)
.then((res) => {
this.getArticlesList(res)
.then((res) => {
this.mergeArticlesList(res)
})
})
})
}
// 1) getCategories() to get the list
getCategories() {
var promise = new Promise((resolve) => {
this.myService.getCategoriesList()
.subscribe((res) => {
this.categories = res;
resolve(this.categories);
})
})
return promise;
}
// 2) getCategoriesIDs(res) to get their IDs and store them in this.ids
getCategoryIDs(res) {
var promise = new Promise((resolve) => {
for (let i=0; i < Object.keys(res).length; i++) {
this.ids[i] = res[i+1]['id']
}
resolve(this.ids)
})
return promise;
}
// 3) getArticlesList(res) to get the list of articles of each category
getArticlesList(res) {
var promise = new Promise((resolve) => {
for (let i=0; i < Object.keys(res).length; i++) {
this.myService.getArticlesOfCategory(res[i])
.subscribe((res) => {
this.allarticleslist[i] = res;
})
}
resolve(this.allarticleslist)
})
return promise;
}
// 4) mergeArticleIds(res) to create another array of ids (this time is // the list of articles' IDs
mergeArticleIds(res) {
console.log("Start merging with:")
console.log(res)
console.log(res.length)
console.log(Object.keys(res).length)
for (let i=1; i < Object.keys(res).length -1; i++) {
for (let _i=0; _i < res[i]['reviews'].length; _i++) {
this.mergedArticles = res[i]['reviews'][_i]['id'] }
}
return this.mergedArticles
}
// 5) getArticle(res) to get the article with that particular ID
// With this http call I finally can get 'article_vote' and I have to
// save this value in order to sort the array.
// It has to return the array sorted
getArticle(res) {
// ??
}
}

It's not working because console.log(res.length) returns 0, so for loop doesn't even start. I know I have to deal with asynchronous operations timing too, but I don't know how to do it.
EDIT: adding getCategoriesList() from myService:
getCategoriesList(): Observable<any[]> {
let url = 'myurl';
return this.httpClient.get(url)
}
EDIT2: adding getCategoriesList()'s http.get response:
{"5":{"description":"","title":"SOCCER""term_id":280,"room_name":"SOCCER"},
"4":{"description":"","title":"NFL","term_id":281,"room_name":"NFL"},
"3":{"description":"","title":"MLB","term_id":282,"room_name":"MLB"},
"2":{"description":"","title":"NHL","term_id":283,"room_name":"NHL"},
"6":{"description":"","title":"TENNIS","term_id":284,"room_name":"TENNIS"},
"1":{"description":"","title":"F1","term_id":285,"room_name":"F1"}}
console.login the code you're showing here, and all of the functions use the variable nameressomewhere in them, so it's not clear which one is showing undefined... As @user2216584 mentioned, HttpClient returns an Observable, which has atoPromise()method on it, so you never have to create new promises like you are. You can also just use Observable to do what you need.