web-dev-qa-db-ja.com

rxjs 6オブザーバブルを適切にチェーンする方法は?

何か提案はありますか、これをより約束の連鎖スタイルでどのように書き直すことができますか?:

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);
                                })
                            );
                        })
                    );
                })
            );
        })
    );
5
askona

switchMap を使用してオブザーバブルを処理し、 tap を使用して副作用を処理できます。そして、それは cold observable なので、サブスクライブする必要があります

エラー処理には、すべてのリクエストに catchError を使用します

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()
1
Kliment Ru

そのためにSwitchMapを使用します。

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

問題には単一のpipeを使用してください。 mapswitchMapmergeMaptapなどのさまざまな連鎖可能な演算子をコンマで区切ります。

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))
);

簡略化:非同期API呼び出しなしで値を変換して別のオペレーターまたはサブスクリプションに渡す場合は、mapを使用し、変換せずに中間の値をキャッチする場合はtapを使用します(例:ロギング用)。また、追加のAPI呼び出しをディスパッチするためのswitchMap

1
ngfelixl