Rxjs:flatMap中的Subject,以避免意外触发

时间:2018-01-19 20:53:12

标签: angular typescript rxjs5

我有一个Angular“Quiz”应用程序并使用 rxjs 5.5.2 来实现具有一些业务逻辑的服务。我的rxjs流程有问题导致多次意外执行函数。

重复步骤:

  1. 调用 startNewQuiz 将新测验设置为有效
  2. 多次致电 answerQuestion 来回答测验问题。每个答案触发在构造函数
  3. 中定义的流
  4. 再次致电 startNewQuiz 以启动另一项测验
  5. 问题是在步骤3中多次调用 startNewQuiz 触发 doStuffWithQuiz 。调试显示这是因为 this.activeQuiz $ 在步骤3中发出一个值并触发 doStuffWithQuiz 。因为我在第2步之前多次调用 answerQuestion - doStuffWithQuiz 也被多次调用。在流程中使用 activeQuiz $ 的唯一原因是获取当前测验并将其传递给管道。

    我希望只有当我将某些内容推送到 answerQuestionSubject 时才会执行 answerQuestionSubject 流程,并且当某些内容被推送到时,我会避免触发 doStuffWithQuiz > activeQuiz $

    那我该如何实现呢?

    export class QuizFlowService {
    
      // to keep current active quiz
      private activeQuiz$ = new ReplaySubject<Quiz>(1);
    
      private answerQuestionSubject = new Subject<Answer>();
    
      ....
    
      constructor() {
        // setup flow for answers
        this.answerQuestionSubject.pipe(
          flatMap(
              // this is just to get active quiz and pass it futher
              () => this.activeQuiz$
          ),
          flatMap((quiz) => {
            // it is called multiple time on step 3
            doStuffWithQuiz(quiz)
          })
        ).subscribe();
      }
    
      // starts new quiz
      startNewQuiz(quiz: Quiz) {
        this.activeQuiz$.next(quiz);
      }
    
      // triggers answer flow
      answerQuestion(answer: Answer) {
        this.answerQuestionSubject.next(answer);
      }
    }
    

1 个答案:

答案 0 :(得分:1)

您应该在第一个flatMap中使用first运算符

flatMap(
    () => this.activeQuiz$.first()
)

由于activeQuiz是一个主题,它可以多次发射。 (步骤3中发生了什么),但是你只关心获得主动测验(1值)。首先,你只会听1个值/发射。