首页 > 解决方案 > 使用 Observables(DRY) 避免重复代码

问题描述

这是来自 Angular 的我的代码(带有重命名的方法):

我有一个函数接口/合约

type IAutocomlete = (
  term: string,
  selectedIds?: string[]
) => Observable<TableFilterQueryResponse[]>;

这是我想在未来注入到我的组件中的草稿服务。我将有更多具有类似实现的方法。

    export class SuperCleanService {
      constructor(
        private dataController: DataController,
        private serviceController: ServiceController
      ) {}
    .....
    private searchAs$: IAutocomlete = (term, selectedIds) => {
        return this.dataController
          .service1GET(term, selectedIds)
          .pipe(
            map((res) =>
              res.map((a) => ({
                viewValue: a.name,
                value: a.id
              }))
            )
          );
      };
      private searchB$: IAutocomlete = (term, selectedIds) => {
        return this.serviceController
          .service1(term, selectedIds)
          .pipe(
            map((res) =>
              res.map((a) => ({
                viewValue: a.id,
                value: a.id
              }))
            )
          );
      };
      private searchC$: IAutocomlete = (term, selectedIds) => {
        return this.dataController
          .service2GET(term, selectedIds)
          .pipe(
            map((res) =>
              res.map((a) => ({
                viewValue: a.name,
                value: a.id
              }))
            )
          );
      };
    ...
    }

我如何重构(遵循 DRY 规则)并使其尽可能干净?我的主要目标是避免在每个函数中使用 map。

标签: javascriptangularrxjsdry

解决方案


自定义运算符

考虑创建一个包含可重用逻辑的自定义运算符。

自定义管道.ts

import { pipe, of } from "rxjs";
import { startWith, switchMap } from "rxjs/operators";

export function myCustomOperator() {
  return pipe(
    map((res) =>
      res.map((a) => ({
        viewValue: a.name,
        value: a.id
      }))
    )
  );
}

您的组件将变为:

export class SuperCleanService {
  constructor(
    private dataController: DataController,
    private serviceController: ServiceController
  ) {}
.....
  private searchAs$: IAutocomlete = (term, selectedIds) => {
    return this.dataController
      .service1GET(term, selectedIds)
      .pipe(
        myCustomOperator()
      );
  };
  private searchB$: IAutocomlete = (term, selectedIds) => {
    return this.serviceController
      .service1(term, selectedIds)
      .pipe(
        myCustomOperator()
      );
  };
  private searchC$: IAutocomlete = (term, selectedIds) => {
    return this.dataController
      .service2GET(term, selectedIds)
      .pipe(
        myCustomOperator()
      );
  };
...
}

推荐阅读