【问题标题】:How to wait until post method finished Angular如何等到发布方法完成Angular
【发布时间】:2020-05-26 22:33:44
【问题描述】:

我正在开发知识测试系统,因此作为管理员,我可以创建测试。 在我创建测试的页面上,首先我输入有关测试和问题计数的信息。 然后对于每个问题,我都会输入该问题的答案计数和有关问题的信息。 然后对于每个答案,我都会输入一些信息,然后单击提交按钮。

动作顺序必须如下:

发布测试 -> 发布第一个问题 -> 发布第一个问题的答案 -> 发布第二个问题等。

所以我需要等到第一个问题被创建,然后为这个问题创建每个答案,然后才为它创建第二个问题和答案。

顺序很重要,一定要按照我写的那样。

但我有一个错误,由于我的 post 方法异步工作,我的订单没有按我想要的方式工作。

例如,如果我为每个问题创建 2 个问题和 2 个答案,我的订单将变成这样:

发布测试完成 -> 发布问题 2 完成 -> 发布问题 1 完成 -> 发布所有答案完成

所以我需要知道,如何等到 post 方法完成。

这是我为他们发布问题和答案的方法:

for(let item of this.sas){// sas is type Map<Question, Answer[]>
      // get question info
      let q = document.getElementById(`q_${ii+1}`) as HTMLInputElement;
      let t = document.getElementById(`t_${ii+1}`) as HTMLInputElement;
      let isSin = true;
      if(t.checked){
        isSin = false;
      }
      let question = new Question();
      question.Content = q.value;
      question.IsSingle = isSin;
      //

      // get answers for this question
      let answers = [];
      for(let j of item[1]){
        let isCorrect = document.getElementById(`a_isCorrect_${ii}:${j}`) as unknown as HTMLInputElement;
        let content = document.getElementById(`a_content_${ii}:${j}`) as unknown as HTMLInputElement;
        let mark =  document.getElementById(`a_mark_${ii}:${j}`) as unknown as HTMLInputElement;

        let answer = new Answer();
        answer.IsCorrect = isCorrect.checked;
        answer.Content = content.value;
        answer.Mark = Number(mark.value);
        answers.push(answer);
        j++;
      }

      //post question
      this.questionService.createQuestion(question).subscribe(data=> {
        console.log(`question ${question.Content} done`);
      //

         //post answers for question
           from(answers).pipe(
             map(answer => this.answerService.createAnswer(answer).subscribe(data => { 
                          console.log(`answer ${answer} done` ) } ) )
           ).subscribe(s=> { console.log("done")});
      //
      });
      ii++;
    };
  }

【问题讨论】:

    标签: javascript angular typescript rxjs


    【解决方案1】:

    这里需要使用concatMap,它会一步步等待每次发射。

    //post question
    this.questionService.createQuestion(question).pipe(
        // executes answers only when question emits.
        concatMap(data=> {
            console.log(`question ${question.Content} done`);
            //
    
            //post answers for question
            return from(answers).pipe(
                concatMap(answer => this.answerService.createAnswer(answer).pipe(
                    tap(data => console.log(`answer ${answer} done` ) ),
                )),
                finalize(() => console.log("done")),
            );
        }),
    ).subscribe();
    

    如果你想要整件事:

    let ii = 0;
    from(this.sas).pipe(
        contactMap(item => {
            // get question info
            let q = document.getElementById(`q_${ii+1}`) as HTMLInputElement;
            let t = document.getElementById(`t_${ii+1}`) as HTMLInputElement;
            let isSin = true;
            if(t.checked){
                isSin = false;
            }
            let question = new Question();
            question.Content = q.value;
            question.IsSingle = isSin;
            //
    
            // get answers for this question
            let answers = [];
            for(let j of item[1]){
                let isCorrect = document.getElementById(`a_isCorrect_${ii}:${j}`) as unknown as HTMLInputElement;
                let content = document.getElementById(`a_content_${ii}:${j}`) as unknown as HTMLInputElement;
                let mark =  document.getElementById(`a_mark_${ii}:${j}`) as unknown as HTMLInputElement;
    
                let answer = new Answer();
                answer.IsCorrect = isCorrect.checked;
                answer.Content = content.value;
                answer.Mark = Number(mark.value);
                answers.push(answer);
                j++;
            }
            ii++;
    
            //post question
            return this.questionService.createQuestion(question).pipe(
                // executes answers only when question emits.
                concatMap(data=> {
                    console.log(`question ${question.Content} done`);
                    //
    
                    //post answers for question
                    return from(answers).pipe(
                        concatMap(answer => this.answerService.createAnswer(answer).pipe(
                            tap(data => console.log(`answer ${answer} done` ) ),
                        )),
                        finalize(() => {
                            console.log("done");
                        ),
                    );
                }),
            );
        }),
        finalize(() => {
          // call done function here.
        ),
    ).subscribe();
    

    【讨论】:

    • 这并不能解决我的问题,我现在的顺序是:测试 -> 问题 1 -> 问题 2 -> 答案 1 -> 答案 3 -> 答案 2 -> 答案 4
    • 然后简单的使用上面的concatMap。我会尽快更新答案。
    • 请看上面。
    • 非常感谢你,它必须炒起来!
    【解决方案2】:

    我相信你最好的选择,只要你不需要发布一堆,可能是这样的递归:

    function handleQuestion(item, index = 0) {
    let q = document.getElementById(`q_${index+1}`) as HTMLInputElement;
    let t = document.getElementById(`t_${index+1}`) as HTMLInputElement;
    let isSin = true;
    if(t.checked){
        isSin = false;
    }
    let question = new Question();
    question.Content = q.value;
    question.IsSingle = isSin;
    
    let answers = [];
    for(let j of item){
        let isCorrect = document.getElementById(`a_isCorrect_${index}:${j}`) as unknown as HTMLInputElement;
        let content = document.getElementById(`a_content_${index}:${j}`) as unknown as HTMLInputElement;
        let mark =  document.getElementById(`a_mark_${index}:${j}`) as unknown as HTMLInputElement;
    
        let answer = new Answer();
        answer.IsCorrect = isCorrect.checked;
        answer.Content = content.value;
        answer.Mark = Number(mark.value);
        answers.push(answer);
        j++;
    }
    
    this.questionService.createQuestion(question).subscribe(data=> {
        from(answers).pipe(
        map(answer => this.answerService.createAnswer(answer).subscribe(data => { 
            console.log(`answer ${answer} done` ) } ) )
        ).subscribe(s=> {
            index++;
            if (this.sas[index]) {
                handleQuestion(this.sas[index], index);
            }
        });
    }); }
    

    【讨论】:

    • 但是第一次调用handleQuestion时应该传入什么参数呢?
    • 并且不允许通过索引从类型Map中获取元素,所以this.sas[index]会一直返回undefined。
    【解决方案3】:

    您可以组合两个可观察对象...以在两者都已响应时获取响应数据。

    fetchData(): Observable<any[]> {
        return combineLatest(
            this.observable1$(),
            this.observable2$()
        );
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-19
      • 1970-01-01
      • 2013-08-19
      • 2021-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-12
      • 1970-01-01
      相关资源
      最近更新 更多