Angular:将间隔与增量和减量相结合

Angular: Combining interval with increment & decrementss

我有一个介于 1 和 20 之间的随机数。 我需要添加按钮来上下移动。 (递增和递减)。 我无法将我的间隔与我的函数结合起来

我的 stackblitz:https://stackblitz.com/edit/angular-ivy-zbrapb?file=src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.css

取1到20之间随机数的函数:

  floor!: Observable<Number>;
  floorNumber = -1;

  ngOnInit(): void {
    this.floor = this.getNumbersInfinite();
  }

  getNumbersInfinite() {
    return interval(1000)
    .pipe(
      map(() => Math.floor(Math.random() * 20) + 1),
      tap(res =>this.floorNumber=res));
  }

执行up和down失败:

 up(){
    if (Number(this.floorNumber) < 20 && Number(this.floorNumber) >= 1) {
       return Number(this.floorNumber++);
    }
    return false;
  }
  down(){
    if (Number(this.floorNumber) < 20 && Number(this.floorNumber) >= 1) {
       return Number(this.floorNumber--);
    }
    return false;
  }

html:

<p>
  {{ floor | async }}
</p>

<input type="button" value="Up" (click)="up()" />
<input type="button" value="down" (click)="down()" />

这应该可以解决问题

export class AppComponent implements OnInit {
  floor = new ReplaySubject<number>(1);

  ngOnInit(): void {
    this.getNumbersInfinite();
  }

  getNumbersInfinite() {
    return interval(1000)
      .pipe(map(() => Math.floor(Math.random() * 20) + 1))
      .subscribe(this.floor);
  }

  up() {
    this.floor
      .pipe(
        take(1),
        filter((v) => v < 20),
        map((v) => v + 1)
      )
      .subscribe((v) => this.floor.next(v));
  }

  down() {
    this.floor
      .pipe(
        take(1),
        filter((v) => v > 1),
        map((v) => v - 1)
      )
      .subscribe((v) => this.floor.next(v));
  }
}

https://stackblitz.com/edit/angular-ivy-dxu7xx?file=src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.css

您可以使用merge() 函数将三个动作合并为一个可观察对象。每次从其中一个可观察对象发生事件时,该值都会发送到模板。

See a working example here.

新模板几乎相同,我们只是删除了点击事件并使用 fromEvent() 在 TypeScript 中创建它。

<p>
  {{ output$ | async }}
</p>

<input type="button" value="Up" #up />
<input type="button" value="down" #down />

TypeScript 将:

  • 创建向上事件
  • 创建按下事件
  • 创建区间
  • 听取所有三个并发出一个可观察到的
export class AppComponent implements AfterViewInit {
  // The current value
  current = 1;

  // Create an Observable from the click event of the up button
  up$!: Observable<number>;
  @ViewChild('up')
  set up(val: ElementRef<HTMLButtonElement>) {
    this.up$ = fromEvent(val.nativeElement, 'click').pipe(
      filter(() => this.current < 20),
      map(() => ++this.current)
    );
  }

  // Create an Observable from the click event of the down button
  down$!: Observable<number>;
  @ViewChild('down')
  set down(val: ElementRef<HTMLButtonElement>) {
    this.down$ = fromEvent(val.nativeElement, 'click').pipe(
      filter(() => this.current > 0),
      map(() => --this.current)
    );
  }

  // Create a timer observable that fires every "x" milliseconds
  interval$ = () =>
    timer(0, 1000).pipe(
      map(() => Math.floor(Math.random() * 20) + 1),
      tap((i) => (this.current = i))
    );

  output$?: Observable<number>;

  // We need to merge here so the buttons are ready.
  // Merging sooner will cause an `undefined` error for the buttons
  ngAfterViewInit() {
    // Merge the three observables and send the results to the template
    this.output$ = merge(this.up$, this.down$, this.interval$());
  }
}