Reputation: 15321
I recently asked a question to prevent a pyramid of doom and got a great answer however as my system advances I need to amend my code and my implementation isn't working.
In my system I subscribe to an Angular Material Dialog afterClose action, I take the result, filter that result, then I call a service that retrieves data (using REST / XHR). When this is resolved I take and modify some of the returned data and return another service method. mergeMap is used to prevent a series of nested .subscribe
s
dialogRef
.afterClosed()
.filter((result) => typeof result === 'string')
.mergeMap((result) => this.myService.getuser(this.id).mergeMap((user: User) => {
const mergedObj = Object.assign({}, user, {LifeEventDate: this.dateService.convertToCorrectFormat(result)});
return this.myService.updateUser(this.id, mergedObj);
}))
.do(() => {
// run some actions in the Component...
})
.subscribe();
Now I wish to take some of the returned data from this.myService.getuser
and call the same service but another method this.myService.logSomething
(which also makes a REST / XHR call). The method this.myService.logSomething
doesn't return any necessary data, when complete it just returns an object {success: true}
although it may be prudent to introduce a .catch
incase of errors. I'd like to add it to the code above, placing it within the second mergeMap doesn't work as when looking in the Chrome Dev tools no network request is made for this. For example...
dialogRef
.afterClosed()
.filter((result) => typeof result === 'string')
.mergeMap((result) => this.myService.getuser(this.id).mergeMap((user: User) => {
/* NEW CODE */
// I need to take some of the data returned from the returned user above
this.myService.logSomething({user:user.id, something: user.something, somethingElse: user.somethingElse});
const mergedObj = Object.assign({}, user, {LifeEventDate: this.dateService.convertToCorrectFormat(result)});
return this.myService.updateUser(this.id, mergedObj);
}))
.do(() => {
// run some actions in the Component...
})
.subscribe();
I am unsure where or how to place this new service call. Both service methods nested in the first .mergeMap
require data from the first service call, how can I add a third service call to my code?
Sorry if the question is badly structured, makes no sense or is unclear please let me know and I'll rephrase.
Upvotes: 2
Views: 1154
Reputation: 96969
I think you could chain multiple mergeMap
(or concatMap
) calls and map the result to the original user
object (I'm assuming that logSomething()
returns an Observable):
dialogRef
.afterClosed()
.filter(...)
.mergeMap((result) => this.myService.getuser(this.id))
.mergeMap(user => this.myService
.logSomething(...)
.map(() => user)) // !!!
)
.mergeMap(user => this.myService.updateUser(...))
.do(() => ...)
.subscribe();
Upvotes: 1
Reputation: 40936
Why are you using mergeMap
? I would try something like this:
dialogRef.afterClosed().filter(...)
.switchMap(e => this.mysService.getUser(this.id))
.switchMap(user => Observable.forkJoin(
this.myService.logSomething(user),
(user) => {
const mergedObj = Object.assign();
return this.myService.updateUser(this.id, mergedObj)
},
(a,b) => b //Selector: return a to pass along the first observable's result
))
.do(...)
.subscribe(...)
Upvotes: 0