kittycatbytes
kittycatbytes

Reputation: 1053

Angular Service function not returning anything, trying to do multiple http requests and return single observable

Unfortunately, the way the site is setup that I need to retrieve data from, is that this data is spread across multiple sites (the exact same type of data and JSON return format) but they are at different URLs. They are classified by the URLs, so I do need to retain the URLs in order to further classify it throughout the app. I have the following service function where I am trying to pass a set of topics (which are then passed to the URL), retrieve the data and return a single observable. However, this is returning nothing:

getDataTopicItems(topicArray) {
    return this.items = topicArray.forEach((topic, i, topicArray) => {
        return this.http.get(this.baseUrl + topic + "/_api/Web/Lists/GetByTitle('What''s New')/items", this.options)
            .map(res => res.json())
            .map(items => items.d.results)
            .do(data => console.log(data))
            .concatMap(data => data)
      }
    )
}

I am subscribing to it in the template of the component where I am calling this function through an *ngFor plus an async pipe. What am I doing wrong?

Update: I also tried the following:

return this.http.get(this.baseUrl + topicArray[0] + this.policyOptions, this.options)
            .map(res => res.json())
            .map(items => this.policies = items.d.results)
            .do(data => console.log(data))
            .flatMap((policies) => topicArray.forEach((topic, i, topicArray) => {
                if (i < 0) {
                    this.http.get(this.baseUrl + topic + this.policyOptions)
                        .map(res => res.json())
                        .map(items => this.policies = items.d.results)
                        .do(data => console.log(data))
                }
            }))

Upvotes: 1

Views: 544

Answers (2)

martin
martin

Reputation: 96969

Callback function to the Array.forEach method doesn't expect to receive anything, so maybe you wanted to use Array.map instead.

If you're looking for "more RxJS" approach you could use mergeMap to do something like this:

return Observable.from(topicArray)
    .mergeMap(topic => this.http.get(this.baseUrl + topic + "/_api/Web/Lists/GetByTitle('What''s New')/items", this.options)
        .map(res => res.json())
        .map(items => items.d.results)
        .do(data => console.log(data))
        .concatMap(data => data);

Eventually you could use concatMap instead of mergeMap to run all requests in order and use concatAll instead of .concatMap(data => data); which makes it a little more obvious what you were trying to do.

Btw, be aware that by using this.items = ... you just assign an Observable to this.items not the result.

Also note that you need to subscribe to the returned Observable if you want to get any results. For example:

getDataTopicItems([...]).subscribe(result => this.items = result);

See live demo: https://jsbin.com/nuzifo/9/edit?html,js,console

Upvotes: 4

Kevin Kipp
Kevin Kipp

Reputation: 427

Array.prototype.forEach returns undefined. See MDN for documentation. Use Array.prototype.map instead, and this.items will be an array of observables that you can then do whatever you want with.

Upvotes: 1

Related Questions