将Observable的先前值与Angular中的下一个值进行比较

jos*_*hke 0 observable rxjs typescript lodash angular

我一直在开发一个应用程序,它允许一些不同的组件BehaviorSubject在Angular中更新.在每个组件中,我存储了前一个BehaviorSubject值的本地副本.为了知道组件是否生成了新值被推出,我计划仅使用LoDash _.isEqual()函数比较两个对象.但是我发现我的本地Observable副本已经更新,然后才能进行比较.

Angular是否查找=语句并在Observable next函数之外创建对该组件属性的外部绑定?

鉴于下面的代码,我发现this.QueryParams组件中的属性已更新为函数中正在处理的当前值,导致我的比较失败,即使我没有将新值分配给属性,直到if评估语句为止.

零件

export class LogsModalComponent implements OnInit {

    private QueryParams: LogsQueryParameters

    ngOnInit() {

        this._LogsService.QueryParameters$.subscribe(_QueryParams => {
            console.log(this.QueryParams);
            console.log(_QueryParams);

            if (!_.isEqual(this.QueryParams, _QueryParams) {
                this.QueryParams = _QueryParams;

                // Some code to process if the new value was different.
            }
        }
    }

    updateStartDate() {
        this.QueryParams.filterStartDate = _.isUndefined(this.FilterStartDate) ? NaN : new Date(this.FilterStartDate.nativeElement.value).getTime();
        this._LogsService.updateQueryParams(this.QueryParams);
}
}
Run Code Online (Sandbox Code Playgroud)

服务

    LogsQueryParameters: BehaviorSubject<LogsQueryParameters> = new BehaviorSubject<LogsQueryParameters>({
            limit: 25,
            logLevels: "",
            logTypes: "",
            logUserIDs: "",
            filterStartDate: NaN,
            filterEndDate: NaN
        })
        LogsQueryParameters$ = this.LogsQueryParameters.asObservable();

    updateQueryParams(QueryParams) {
        this.LogsQueryParameters.next(QueryParams);
    }
Run Code Online (Sandbox Code Playgroud)

Jef*_*amp 6

RxJS observables有一个方法distinctUntilChanged()返回一个新的observable,如果它与先前发出的值不同,它只发出一个新的值:

this._LogsService.QueryParameters
    .distinctUntilChanged()
    .subscribe((_QueryParams) => this.QueryParams = _QueryParams);
Run Code Online (Sandbox Code Playgroud)

这适用于简单的比较.如果您_.isEqual仍然需要该功能,则可以传递回调distinctUntilChanged()来执行比较:

this._LogsService.QueryParameters
    .distinctUntilChanged((prev, curr) => _.isEqual(prev, curr))
    .subscribe((_QueryParams) => this.QueryParams = _QueryParams);
Run Code Online (Sandbox Code Playgroud)

请注意! ...,只要返回值为false(意味着测试中的值不相等),您就不会返回回调内部,值会通过.

更新

从你最新的编辑看,你实际上正在传递完全相同的对象,只是改变其内容,正如@Brandon在下面的评论中所建议的那样.您可以尝试在更新时创建新对象,方法是Object.assign():

updateStartDate() {
    this.QueryParams.filterStartDate = _.isUndefined(this.FilterStartDate)
        ? NaN 
        : new Date(this.FilterStartDate.nativeElement.value).getTime();
    this._LogsService.updateQueryParams(Object.assign({}, this.QueryParams));
}
Run Code Online (Sandbox Code Playgroud)

对象实际上是通过引用传递的.

请注意,它new Date()也会返回一个对象.该对象也通过引用传递和分配,只有这一次Object.assign不会帮助你,因为date对象依赖于原型链接(它不是普通对象).


Anh*_*ang 5

对于那些想要将 Observable(或 BehaviourSubject)的先前值与当前值进行比较的人,只需使用成对运算符即可。例如:

ngOnInit() {
    this._logsService.yourObservable$.pipe(pairwise()).subscribe(([previous, current]) => {
        if (previous !== current) {
            // Some code to process if the new value was different.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 考虑到如果你使用pairwise,只有当有多个值时才执行,所以通常你需要添加 startWith `$observable.pipe(startWith(actual_value),pairwise())..)` (2认同)