askona
askona

Reputation: 410

How to properly chain rxjs 6 observables?

Any suggestions, how this can be rewritten in more promise-chaining style?:

this.apiService.sendPutRequest('/api/users/activate', usrObj).pipe(
        map(() => {
            return this.apiService.sendGetRequest('/api/users/' + this.currentUserId).pipe(
                map(data => {
                    return this.setActiveUser(data).pipe(
                        map(() => {
                            return this.apiService.sendGetRequest('api/tasks/user/' + this.currentUserId).pipe(
                                map(tasks => {
                                    return this.taskService.setCurrentUserTasks(tasks);
                                })
                            );
                        })
                    );
                })
            );
        })
    );

Upvotes: 12

Views: 15834

Answers (3)

Felix Lemke
Felix Lemke

Reputation: 6488

Use a single pipe for your problem. Just comma seperate different chainable operators like map, switchMap, mergeMap, tap, etc.

this.apiService.sendPutRequest('/api/users/activate', usrObj).pipe(
  switchMap((results) => this.apiService.sendGetRequest('/api/users/' + this.currentUserId)),
  tap((results) => this.setActiveUser(data)),
  switchMap(() => this.apiService.sendGetRequest('api/tasks/user/' + this.currentUserId)),
  tap((results) => this.taskService.setCurrentUserTasks(tasks))
);

Simplified: Use map if you just want to transform a value without any async api calls and pass it to another operator or a subscription, tap if you just want to catch values in between without transforming (e.g. for logging). And switchMap for dispatching additional api calls.

Upvotes: 8

Kliment Ru
Kliment Ru

Reputation: 2137

You can use switchMap for handling observables and tap for side efects handling. And you need to subscribe because it's cold observable

For error handling use catchError for all requests

this.apiService.sendPutRequest('/api/users/activate', usrObj).pipe(
    catchError(err=> this.errorHandler(err)),
    switchMap(() => this.apiService.sendGetRequest('/api/users/' + this.currentUserId)
        .pipe(catchError(err=> this.errorHandler(err)))
    ),
    tap(data => this.setActiveUser(data)),
    switchMap(() => this.apiService.sendGetRequest('api/tasks/user/' + this.currentUserId)
        .pipe(catchError(err=> this.errorHandler(err)))
    ),
    tap(tasks => this.taskService.setCurrentUserTasks(tasks))
).subscribe()

Upvotes: 15

Antoniossss
Antoniossss

Reputation: 32535

use SwitchMap for that.

mainApiCall.pipe(
    switchMap(result=>secondApiCall(result)),
    switchMap(resultFromSecondApiCall=>thirdApiCall(resultFromSecond))
...
and so on
)

Upvotes: 12

Related Questions