Shawn Lauzon Shawn Lauzon - 9 months ago 47
Javascript Question

Using rxjs, how to map each element to multiple elements

I suspect this isn't hard, but I can't figure out how to do it. I have an array of objects, and each object contains an array. After doing some additional processing, I want to retrieve a remote resource for each of the elements. My problem is that my function returns an array, but I want the elements of the array separate.

return Rx.Observable.from([ // 1
{ "rosters": ["a/name1", "b/name2"] },
{ "rosters": ["c/name3", "c/name4"] }])
.map(group => group.rosters) // 2
.map(roster => roster.substring(0, roster.indexOf('/'))) // 3
.distinct() // have I seen this before?
.map(folder => http.get(URL + folder + '/ads.json').map(res => res.json())
.map(adData =>
.reduce(/* choose random ad */);

I want the function at #2 to return data such that each enter of #3 is a separate string. Right now coming into #3 are arrays (in my example pairs of strings). Thanks!

Answer Source

With assistance both from the OP as well as from @tmslnz...

Change .map(group => group.roster) to .flatMap(group => group.roster).

With a plain array like this, I suspect this is good enough. However, just to future-proof this, I wonder whether concatMap might be more strictly appropriate than flatMap. The rxjs documentation indicates that flatMap merges results which could cause the results to be interleaved, while concatMap strictly concatenates them, with no interleaving. Again, for your current use case, flatMap seems fine, but I thought this distinction was worth noting, e.g. in case future uses (or other readers' uses) require strict ordering in the face of possible result overlap. In any case, concatMap also seems to produce the correct results here.