如何 return 扫描后用插入的项目更新数组?

How to return updated array with inserted item after scan?

我有以下代码:

public checkedRoles$ = merge(this.roles$, this.roleChanged$).pipe(
    tap((data) => console.log(data)),
    scan((roles: Role[], role: Role) => {
        console.log(roles);
        return roles.map((r) => (role && r.roleId === role.roleId ? role : r));
    }),
    map((roles) => roles.filter((r) => r.checked)),
);

当我获得更新的对象数组时 this.roles$ 我可以在扫描前看到结果:tap((data) => console.log(data)),

但是我没有在 console.log(roles); 中的 scan() 中得到这个数组。如何始终获得带有选中项目的新数组?

这是我在上面尝试过的最简单的无 Rxjs 方式:

private checkedRoles$ = new BehaviorSubject<any[]>([]);

readonly roleChangeSubject = new Subject<Role>();
roleChanged$ = this.roleChangeSubject.asObservable();
this.roleChanged$.subscribe((role: any) => {
            let roles = this.roles$.getValue();

            roles.forEach((r: Role) => {
                if (role.roleId === r.roleId) r.checked = role.checked;
            });

            this.checkedRoles$.next(roles);
        });

我认为这应该会如您所愿。正如您所说,只是您在扫描返回之前记录了之前的 roles

如果在 scan 之后再添加一个 tap 就可以看到这个:

public checkedRoles$ = merge(this.roles$, this.roleChanged$).pipe(
  tap((data) => console.log('New role change:', data)),
  scan((roles: Role[], role: Role) => {
    return roles.map((r) => (role && r.roleId === role.roleId ? role : r));
  }),
  tap((data) => console.log('Updated roles:', data)),
  map((roles) => roles.filter((r) => r.checked)),
);

另一方面,merge 可能不在这里,因为 roles$roleChanged$ 是不同的类型。

如果roles$发出一次,那么你可以使用concat代替,然后它将只用作[=14]的初始值=]:

public checkedRoles$ = concat(this.roles$, this.roleChanged$).pipe(
  scan((roles: Role[], role: Role) => {
    return roles.map((r) => (role && r.roleId === role.roleId ? role : r));
  }),
  map((roles) => roles.filter((r) => r.checked)),
);