我正在try 实现一个httpService,其中我们有3个Rest API端点.如果第一个API返回成功代码,那么我不想调用下一个端点,但如果出现错误,我想try 第二个或第三个端点. 我写的代码就像

从‘rxjs’导入{of,throwError}; 从‘rxjs/OPERATOR’导入{catchError,mergeMap};

this.httpService
  .post(`${primary_system}?id=${params.id}`)
  .pipe(
    catchError((primaryError) => {
      if (!!secondary_system) {
        return this.httpService
          .post(`${secondary_system}?id=${params.id}`)
          .pipe(
            catchError((secondaryError) => {
              if (!!tertiary_system) {
                return this.httpService.post(`${tertiary_system}?id=${params.id}`);
              }
              return of(secondaryError);
            })
          );
      }
      return of(primaryError);
    })
  );

当然,这将是扁平化这些嵌套调用的一种方式.我认为这是一种不好的做法,不能像这样管可观测到的东西.还有更好的解决方案吗?

推荐答案

您不需要将第二个catchError嵌入到第一个catchError的闭合中.

换句话说,你可以做这样的事情

this.httpService
  .post(`${primary_system}?id=${params.id}`)
  .pipe(
    catchError((primaryError) => {
      if (!!secondary_system) {
        return this.httpService
          .post(`${secondary_system}?id=${params.id}`)
          );
      }
      return of(primaryError);
    }),
    // here you catch an error that is generated by the call to the
    // secondary system
    catchError((secondaryError) => {
      if (!!tertiary_system) {
         return this.httpService.post(`${tertiary_system}?id=${params.id}`);
      }
      return of(secondaryError);
    })
  );

您还可以通过引入2个函数来表示对第二和第三系统的调用,从而使代码更具可读性,如下所示

// this function returns an Observable that represents the call to the
// secondary system if it catches an error coming from upstream
function callSecondIfFirstFail(id: any) {
   return pipe(
      catchError((primaryError) => {
        if (!!secondary_system) {
          return this.httpService.post(`${secondary_system}?id=${id}`));
        }
        return of(primaryError);
      }),
   )
}

// this function returns an Observable that represents the call to the
// tertiary system if it catches an error coming from upstream
function callThirdIfSecondFail(id: any) {
   return pipe(
      catchError((secondaryError) => {
        if (!!tertiary_system) {
          return this.httpService.post(`${tertiary_system}?id=${id}`));
        }
        return of(secondaryError);
      }),
   )
}

// this is then how the code that performs the, possible, three calls
// would look like
this.httpService
  .post(`${primary_system}?id=${params.id}`).pipe(
     callSecondIfFirstFail(params.id),
     callThirdIfSecondFail(params.id)
  )

stackblitz个试图代表这个 idea .

Typescript相关问答推荐

当类型断言函数返回假时,TypScript正在推断从不类型

将props传递给子组件并有条件地呈现它''

HttpClient中的文本响应类型选项使用什么编码?''

如何将类型从变量参数转换为返回中的不同形状?

如何使用一个字段输入对象,其中每个键只能是数组中对象的id属性,而数组是另一个字段?

TypeScrip 5.3和5.4-对`Readonly<;[...number[],字符串]>;`的测试版处理:有什么变化?

返回具有递归属性的泛型类型的泛型函数

如何将定义模型(在Vue 3.4中)用于输入以外的其他用途

RXJS将对键盘/鼠标点击组合做出react

如何在Angular 服务中制作同步方法?

打字错误TS2305:模块常量没有导出的成员

如何创建内部和外部组件都作为props 传入的包装器组件?

字幕子集一个元组的多个元素

如何创建一个将嵌套类属性的点表示法生成为字符串文字的类型?

如何从抽象类的静态方法创建子类的实例?

将带有额外id属性的Rust struct 展平回TypeScript单个对象,以返回wasm-bindgen函数

如何在Vuetify 3中导入TypeScript类型?

我可以使用对象属性的名称作为对象中的字符串值吗?

我应该使用服务方法(依赖于可观察的)在组件中进行计算吗?

是否可以使用元组中对象的键来映射类型