如何在观察网络的 Observables 上使用声明模式?

How to use a declarative pattern on Observables that watch the network?

我一直在尝试了解 rxjs 中的声明式 pattern/approach,根据我的理解,它不直接在打字稿本身中使用 .subscribe() 而是使用 async 管道.

我有一个 class 保存有关图像的数据,其中一些数据是 tags 属性,它是一个字符串数组。通过 UI 你可以 add/remove 标签到这个 属性。当您保存一个新项目时,该值通过 websocket 发送到服务器,套接字将发回所有项目标签的列表(包括新添加的标签)。

因此,我创建了一个侦听器,用于侦听 websocket 何时响应与图像标签相关的数据。当它看到此消息时,它应该更新此图像对象中的所有标签。

类似于下面的伪代码:


interface FileInfo {
  tags: string[];
}

@Component({
  template: `
    <div *ngIf="image$ | async as image">
      <div *ngFor="let tag of image.tags">{{tag}}</div>
    </div>
  `
})
export class MyComponent {
  image = new BehaviorSubject<FileInfo | null>(null);
  image$ = this.image.asObservable();

  ngOnInit() {
    this.websocket.on('tags:image').pipe(
      map(i => i.data) // i.data is an array of strings
      tap(strs => this.image.value = strs)
    );
  }
}

现在,当消息返回时,它应该更新图像对象并重新呈现组件。 如果不在 this.websocket.on() 上使用订阅,这 pattern/approach 怎么可能?这一切所做的就是监视网络并修改对象上的 属性。


我将上面的修改为这种模式,但我不太喜欢我现在在做 .next() 时必须管理多个 属性,这种方法似乎不对似乎很容易使 image.tagstags$.

的值不同步
@Component({
  template: `
    <div *ngIf="image$ | async as image">
      <div *ngFor="let tag of tags$ | async">{{tag}}</div>
    </div>
  `
})
export class MyComponent {
  image = new BehaviorSubject<FileInfo | null>(null);
  image$ = this.image.asObservable();

  tags = new BehaviorSubject<string[]>([]);
  tags$ = merge(this.tags, this.websocket.on('tags:image')).pipe(
    map(i => i.data) // i.data is an array of strings
  );

  ngOnInit() {
   // I want to get rid of this subscribe too
   // However this is the next
   this.manageService.$collectionEvents.subscribe(event => {
     this.image.next(event.image);
     this.tags.next(event.image.tags);
    });
  }
}

它会像这样(我刚刚制作了一个可观察的 data$ 来模拟您的网络套接字响应):

  image$ = new Observable<FileInfo>();

  ngOnInit() {
    const data$ = of({ data: ['string1', 'string2', 'string3'] });
    this.image$ = data$.pipe(
      map((i) => {
        return { tags: i.data };
      })
    );
  }

在您的上下文中

  image$ = new Observable<FileInfo>();

  ngOnInit() {
    this.image$ = this.websocket.on('tags:image').pipe(
      map((i) => {
        return { tags: i.data };
      })
    );
  }

异步管道将自动订阅 image$ 并在组件销毁时取消订阅。每当 observable 收到新值时,它也会处理更新 html。

这是一个 stackblitz,我在其中模拟每秒变化的可观察值:https://stackblitz.com/edit/angular-ivy-m2digv?file=src/app/app.component.ts