【问题标题】:RxJS: Have Observables only emit values after the previous Observable has completedRxJS:让 Observables 仅在前一个 Observable 完成后才发出值
【发布时间】:2020-09-27 09:52:33
【问题描述】:

我目前正在尝试实现一个 Angular 结构指令,它将读取和存储 HTML 元素(及其所有子元素)的文本内容,在 AfterViewInit 上删除其内容,并延迟重新添加内容,一次一个字符,使其看起来像是实时输入的。

我通过分析目标节点的 NodeType 来做到这一点。如果是文本,它会将数据内容备份到一个数组中并继续处理下一个元素。如果它是不同的节点,它也会递归地分析该节点。这样,我还可以修改目标元素的另一个 HTMLElement 中包含的文本。

为了将文本写回节点,我使用了 Observables。每个节点的原始值一次发出一个字符,每个字符之间有 60 毫秒的延迟,将其重新添加到原始节点的内容中以模拟键盘输入延迟。在我的 anaylze 方法中,我还收集了前一个节点内容的长度,将 Observable 延迟了该数字 * 60ms。我的意图是让下一个 Observable 仅在前一个 Observable 完成后才发出它的值。

但是(可能是由于 Observable 的异步特性)通常一个 Observable 会在前一个完全完成之前开始发射值。这有时会使页面看起来好像一次添加了多行,这是我试图避免的行为。

这就是我的 Observables 的样子:

from(this.mementos)
  .pipe(
    concatMap(
      memento => of(memento).pipe(delay(memento.previousNodeLength * 60)) // delay Observable by the time it takes to complete the previous node
    )
  )
  .subscribe(memento =>
    from(Array.from(memento.data))
      .pipe(concatMap(text => of(text).pipe(delay(60)))) // delay each character by 60ms
      .subscribe(c => {
        memento.node.data += c;
      })
  );

展示问题的完整工作 Stackblitz: Stackblitz Example

如何修改我的代码以便一次只添加一个节点的内容?

【问题讨论】:

    标签: angular rxjs reactive-programming angular-directive


    【解决方案1】:

    使用n * 60 计算延迟会为您提供准确的数字,但如果使用n setTimeout()s 模拟相同的延迟,它将不匹配,因为setTimeout() 不能保证确切的超时。

    因此,您可以删除嵌套的 Observable 并创建一个链,使用 concatMap 将首先获取每个纪念品,然后是每个字符。

    from(this.mementos)
      .pipe(
        concatMap(memento => from(memento.data).pipe( // each memento
          concatMap(char => of({ node: memento.node, char }).pipe(delay(60))), // each char
        ))
      )
      .subscribe(({ node, char }) => {
        node.data += char;
      });
    

    只有在前一个备忘录完成后,才会开始处理下一个备忘录。每个字符都在嵌套的 Observable 中延迟。

    现场演示:https://stackblitz.com/edit/angular-ivy-njfysl?file=src/app/typewriter.directive.ts

    【讨论】:

      猜你喜欢
      • 2021-01-24
      • 2022-12-06
      • 1970-01-01
      • 2021-08-28
      • 2018-04-08
      • 1970-01-01
      • 2016-10-31
      • 1970-01-01
      • 2017-07-30
      相关资源
      最近更新 更多