使用 Observables(DRY) 避免重复代码

Elm*_*aul 5 javascript dry rxjs angular

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

我有一个函数接口/契约

type IAutocomlete = (
  term: string,
  selectedIds?: string[]
) => Observable<TableFilterQueryResponse[]>;
Run Code Online (Sandbox Code Playgroud)

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

    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
              }))
            )
          );
      };
    ...
    }
Run Code Online (Sandbox Code Playgroud)

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

fab*_*tto 0

export class SuperCleanService {
    constructor(
    private dataController: DataController,
    private serviceController: ServiceController
    ) {}

    private performSeach: = (caller, resultMapper) => {
        return caller()
        .pipe(
            map((res) =>
                res.map(resultMapper)
            )
        );
    }

    private searchAs$: IAutocomlete = (term, selectedIds) => {
        return this.performSeach(
            () => this.serviceController.service1GET(term, selectedIds),
            (a) => ({
                viewValue: a.name,
                value: a.id
            })
        )
    };

    private searchB$: IAutocomlete = (term, selectedIds) => {
        return this.performSeach(
            () => this.serviceController.service1(term, selectedIds),
            (a) => ({
                viewValue: a.id,
                value: a.id
            })
        )
    };

    private searchC$: IAutocomlete = (term, selectedIds) => {
        return this.performSeach(
            () => this.serviceController.service2GET(term, selectedIds)
            (a) => ({
                viewValue: a.name,
                value: a.id
            })
        )
    };
}
Run Code Online (Sandbox Code Playgroud)

我会先做这样的事情 - 抱歉我没有添加正确的 Typescript 注释,但我想你明白了。和argscallermapper两个回调。

这样您就不会重复调用管道和映射的逻辑,您可以自由地使用不同的参数和映射函数。此外,您的方法仍然是显式的,它们可以接受任意参数,并且可以在调用内部搜索方法之前执行额外的逻辑,而无需太多魔法。