typescript RxJS:修改管道链下游的先前值

5vf7fwbs  于 2023-02-05  发布在  TypeScript
关注(0)|答案(1)|浏览(154)

在我的项目中,我遇到了一个有趣的例子,在一个管道链中执行多个请求,这都是关于在quill文本编辑器中显示图像的。
后端以如下形式返回内容:

content: "<img alt="alt.png" id="1234567890"><p>content</p>"

正如你所看到的,图像中缺少src属性,我们需要2个额外的api来获取它,这是很困难的,因为我们操作的是图像的id,它被缝合成字符串。
不正确的解决方案只为理解本质的目的!

ngOnInit(): void {
    this.selectedTemplate
      .pipe(
        map(e => {
            const document = new DOMParser().parseFromString(e.content, 'text/html');
            document.querySelectorAll('img').forEach(img => {
              this._imageService.getImageToken(img.getAttribute('id')).pipe(
                switchMap(result => {
                    return this._imageService.getImageByToken(result.token);
                })).subscribe(result => {
                    img.setAttribute('src', result)
                });
            });
            return {
                ...e,
                content: document.body.innerHTML
            }
        }),
        tap(e => this.form.setValue({ id: e.id, content: e.content, title: e.name })),
      )
      .subscribe();
  }

我希望所有的数据在进入点击操作员之前都被获取。就目前而言,解决方案是可行的,但看起来很糟糕。有什么想法可以在不触及后端的情况下改进这个问题吗?

isr3a4wc

isr3a4wc1#

下面是我将要执行的一个快速重构。
这将一些臃肿的逻辑提取到自己的函数中,并且还返回一个可观察的而不是嵌套的订阅。
需要考虑的是,用于处理DOMDocs的命令式API不太适合Observables,最终得到的是一个排序文档效果而不是转换值的流。
如果这是一个小项目,那很好。否则我会进一步重构它,将文档上的所有变化分离到一个单独的逻辑单元中。这是需要考虑的。

_setImgSources(document: Document): Observable<Document> {
  return merge(...
    [...document.querySelectorAll('img')].map(img => 
      this._imageService.getImageToken(img.getAttribute('id')).pipe(
        switchMap(imgToken => this._imageService.getImageByToken(imgToken.token)),
        tap(imgSrc => img.setAttribute('src', imgSrc)),
      )
    )
  ).pipe(
    ignoreElements(),
    endWith(document)
  );
}

ngOnInit(): void {
  this.selectedTemplate.pipe(

    switchMap(templ => 
      this._setImgSources(
        new DOMParser().parseFromString(templ.content, 'text/html')
      ).pipe(
        map(doc => ({
          ...templ, 
          content: doc.body.innerHTML
        }))
      )
    ),

  ).subscribe(({id, content, name}) => this.form.setValue({ 
    id, 
    content, 
    title: name 
  }));

}

相关问题