如何从另一个 .pipe() 内部将参数传递给包装的“.pipe()”逻辑

How to pass parameters to wrapped '.pipe()' logic from inside of another .pipe()

我必须为不同的服务调用执行相同的逻辑(例如:myService.getA()myService.putA())。该逻辑包括其他服务调用,因此我从 .pipe().

中进行这些调用

我现在的逻辑是这样的:

this.myService.getItemA()
    .pipe(
        filter(itemA => {
            if (itemA.property) {
                this.itemA = itemA;
                return true;
            } else {
                this.someLogic(itemA);
                return false;
            }
        }),
        switchMap(() => this.anotherService.getItemB()),
        tap(itemB => {
            this.anotherLogic(itemB);
            this.someLogic(this.itemA);
        })
    ).subscribe();
this.myService.putItemA()
    .pipe(
        filter(itemA => {
            if (itemA.property) {
              this.itemA = itemA;
              return true;
            } else {
              this.someLogic(iteamA);
              return false;
            }
        }),
        switchMap(() => this.anotherService.getItemB()),
        tap(itemB =>{
            this.anotherLogic(itemB);
            this.someLogic(this.itemA);
        })
    ).subscribe();

我在 中发现的是,它可以通过将共享逻辑包装在函数变量中来完成:

private prepareData= (itemA: IteamA) => pipe(
    filter(() => {
      if (itemA.property) {
        this.itemA = itemA;
        return true;
      } else {
        this.someLogic(iteamA);
        return false;
      }
    }),
    switchMap(() => this.anotherService.getItemB()),
    tap(itemB => {
        this.anotherLogic(itemB);
        this.someLogic(this.itemA);
    })
  );

然后像这样使用它:

this.myService.putItemA()
    .pipe(
        tap(itemA=> this.temporaryIteamA = this.itemA)
        this.prepareData(this.temporaryItemA)
    ).subscribe();

但是,考虑到我的 putItemA() 已经 returns 一个 Observable<ItemA> 我想像下面这样写:

this.myService.putItemA()
    .pipe(
        this.prepareData(itemA)
    ).subscribe();

this.myService.getItemA()
    .pipe(
        this.prepareData(itemA)
    ).subscribe();

我应该如何修改 prepareData() 以隐式接收数据?

我认为您的情况不需要包装纸。

只需尝试以下操作:

import { pipe } from 'rxjs'

const prepareData = pipe(
  filter(itemA => {
    if (itemA.property) {
      this.itemA = itemA;
      return true;
    } else {
      this.someLogic(itemA);
      return false;
    }
  }),
  switchMap(() => this.anotherService.getItemB()),
  tap(itemB => {
    this.anotherLogic(itemB);
    this.someLogic(this.itemA);
  })
);

然后

this.myService.getItemA().pipe(prepareData).subscribe(...)

this.myService.putItemA().pipe(prepareData).subscribe(...)

每当你使用 Observable 管道时,顾名思义,所有的 emmited 值都会 piped 进入定义的管道(将其视为真实管道),因此你可以做任何操作,修改值,改变发射源,以及更多更复杂的场景。

也就是说,当您创建自定义管道(或运算符)时,您可以直接将其定义为管道...

const myPipe = pipe(
    switchMap(emmitedValue => of(`${emmitedValue} How are you?`))
);

或者您可以将其定义为 return 管道的函数...

const myPipe2 = optionalMessage => pipe(
  switchMap((emmitedValue) => of(`${emmitedValue} How are you? ${optionalMessage}`))
);

然后你可以使用这些管道,第一个通过传递它的引用(你仍然会在那里收到 emmited 值),第二个通过调用 return 所需管道的函数(因此你可以传递的参数不仅仅是 emmited 值)。

of('Biiz').pipe(
  map(x => `Hello ${x}!`),
  myPipe,
).subscribe(console.log);

of('Biiz').pipe(
  map(x => `Hello ${x}!`),
  myPipe2(`It's a sunny day `),
).subscribe(console.log);

(你可以检查那个例子here

对于您的情况,您应该通过在管道中接收发射值来定义自定义运算符:

private prepareData = pipe(
    filter((itemA: IteamA) => {
      if (itemA.property) {
        this.itemA = itemA;
        return true;
      } else {
        this.someLogic(iteamA);
        return false;
      }
    }),
    switchMap(() => this.anotherService.getItemB()),
    tap(itemB => {
        this.anotherLogic(itemB);
        this.someLogic(this.itemA);
    })
  );

并通过传递它的引用来使用它:

  this.myService.putItemA()
      .pipe(
          this.prepareData
      ).subscribe();
  
  // or
  
  this.myService.getItemA()
      .pipe(
          this.prepareData
      ).subscribe();