使用filter()时更新下一个值的RxJS延迟

时间:2017-10-03 17:49:11

标签: javascript angular rxjs

我有这段代码:

app.component.ts:

import {Component, AfterViewInit, ChangeDetectorRef} from '@angular/core';
import {Subject} from 'rxjs/Subject';

import 'rxjs/add/operator/scan';
import 'rxjs/add/operator/filter';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
    changes$ = new Subject<number>();
    current$ = this.changes$
        .scan((x, y) => x + y, 0)
        .filter((x) => x >= 0);
    constructor(private cdRef: ChangeDetectorRef) {}

    ngAfterViewInit(): void {
        this.changes$.next(0);
        this.cdRef.detectChanges();
    }
}

app.component.html:

<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
    <button (click)="changes$.next(-1)">-1</button>
    <button (click)="changes$.next(1)">+1</button>

    <div>
        <span>{{ current$ | async }}</span>
    </div>
    <div>
        <span>{{ current$ | async }}</span>
    </div>
    <div>
        <span>{{ current$ | async }}</span>
    </div>
</div>

我的问题是我不想低于0所以我添加了过滤器运算符。这解决了我的问题,但是当我到0并按下负按钮10次然后再次按下添加按钮时,除非我多次按下添加按钮,否则它不会更新。

这是为什么?我该如何解决?

示例:

The problem in GIF

2 个答案:

答案 0 :(得分:3)

在扫描中尝试此操作。原因是每次发出一个值时,无论是否过滤,都会处理扫描。

.scan((x, y) => (x + y) >= 0 ? x + y : 0, 0)

答案 1 :(得分:1)

嗯,首先 - 正如迪帕克所说,你需要把它移到scan()。原因是当changes$主题发出新值scan()时,仍会继续计算它发出的任何内容,包括负数,但您不会从filter()后面看到它。如果您不希望计数器低于0,而不是按filter()屏蔽其输出,则需要精确停止计数。

此外,您不需要手动发出第一个值,也不需要构造函数和ngAfterViewInit调用ChangeDetectorRef。这一切都是完全没必要的。

以下是固定代码:

import {Component} from '@angular/core';
import {Subject} from 'rxjs/Subject';
import 'rxjs/add/operator/scan';
import 'rxjs/add/operator/startWith';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    changes$ = new Subject<number>();
    current$ = this.changes$
        .startWith(0)
        .scan((x, y) => (x + y) >= 0 ? x + y : 0, 0);
}