首页 > 解决方案 > RxJS 在 subscribe 内部订阅,并在错误时执行操作

问题描述

我有subscribe里面的代码subscribe

this.http.post('/update1', newData).subscribe(
    (response) => {
        const r = response.json;
        const id = r['id'];
        this.http.post('/update2?id=' + id, newData).subscribe(
            () => {
                this.http.post('/update3?id=' + id, newData).subscribe(
                    () => {
                        console.log('success');
                    },
                    () => {
                        // revert changes made to update2
                        this.http.post('/update2', previousValues).subscribe();
                        // revert changes made to update1
                        this.http.post('/update1', previousValues).subscribe();
                    });
            },
            () => {
                // revert changes made to update1
                this.http.post('/update1', previousValues).subscribe();
            }
        );
    },
    (error) => {
        console.log(error);
    }
);

如何在 RxJS 5 中优化它?

标签: angulartypescriptrxjsrxjs5

解决方案


请不要在另一个订阅中使用订阅。使用原生 RxJS 操作符,有更好的解决方法是:

this.http
  .post('/update1', newData)
  .pipe(
    map((response) => response.json),
    map((data) => data.id),
    switchMap((id) =>
      this.http.post('/update2?id=' + id, newData).pipe(
        switchMap(() => this.http.post('/update3?id=' + id, newData)),
        catchError((err) => {
          // this catcherror will happen if update3 failes
          return merge(
            // revert changes made to update2
            this.http.post('/update2', previousValues),
            // revert changes made to update1
            this.http.post('/update1', previousValues),
          );
        }),
      ),
    ),
    catchError((err) => {
      // this catcherror will happen if update2 failes
      // revert changes made to update1
      return this.http.post('/update1', previousValues);
    }),
  )
  .subscribe(
    (result) => {
      console.log(result);
    },
    (err) => {
      // this error will happen if an error happens wich is not caught
      console.log(err);
    },
  );

这样,如果您愿意,您只有一个订阅方法来处理最后剩余的结果。

请记住,catchError()如果在任何地方之前触发异常,内部管道将被触发。如果异常已被处理程序处理,则完全相同的异常不会触发其他catchError()两次。


推荐阅读