Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.8k views
in Technique[技术] by (71.8m points)

angular - Performing advanced http requests in rxjs

I have the following objects:

class Question {
    idQuestion: string;
    question: string;
    typeQuestion: string;
}

class Answer {
    idAnswer: string;
    idQuestion: string;
    answer: string;
}

class Option {
    idOption: string;
    idQuestion: string;
    option;
}

And I want to populate the following object:

class QuestionOptionsAnswer {
    question: Question;
    answer: Answer;
    options: Option[];
}

For now, I have a service for each kind of object, so we can illustrate it in the following way:

questionService.getQuestions();
answerService.getAnswers();
optionService.getOptions();

To populate a questionoptionsanswer object I have doing nested requests:

questionService.getQuestions()
    .subscribe(
        answerService.getAnswers()
           .subscribe(
               optionService.getOptions()
                  .subscribe();
           )
    )

I can populate correctly the questionoptionsanswer object, but is is slow, so I think I am making a bad approach. The idea behind having a questionoptionsanswer is for rendering in a easy way the html with angular2 directives.

I read about flatMap, switchMap, forkJoin but I am not quite sure in how to use them.

Which could be a good approach to load this data?

questionoptionsanswer will have a question object, an answer associated with it, and its possible options depending on the typeQuestion i.e: select, radio, multiple, etc.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So you need to call the first request and wait for its response and then call the two other requests (for options and the answer) at the same time.

Since I want to know when both responses are ready I'll use Observable.forkJoin() operator that emits a single array with all values of source Observables when they completed and then add data to the qoa variable that I'll just pass to the Observer when it subscribes.

Operators such concat() or concatMap() are good to make multiple HTTP calls in order but not very useful when you need to create multiple Observable to construct one large response you want to emit (QuestionOptionsAnswer in your case).

I also used Observable.of(...) to simulate HTTP requests. I don't know what's your usecase so you'll maybe don't use Observable.create() and use Subject instead:

function getQOA() {
    return Observable.create(observer => {

        Observable.of({ question_id: '1' }).subscribe(response => {
            var qoa = new QuestionOptionsAnswer();
            let question = new Question();
            question.idQuestion = response.question_id;

            qoa.question = question;

            let obs1 = Observable.of({ answer_id: '1', answer: 'bla' });
            let obs2 = Observable.of([{ option_id: '1', option: 'ble' }]);

            Observable.forkJoin(obs1, obs2).subscribe(responses => {
                let [answerResponse, optionsResponse] = responses;

                let answer = new Answer();
                answer.idAnswer = answerResponse.answer_id;
                answer.answer = answerResponse.answer;
                qoa.answer = answer;

                qoa.options = optionsResponse.map(o => {
                    let option = new Option();
                    option.idOption = o.option_id;
                    option.option = o.option;
                    return option;
                });

                observer.next(qoa);
            });
        });
    });
}

getQOA().subscribe(qoa => console.log(qoa));

Prints to console:

QuestionOptionsAnswer {
  question: Question { idQuestion: '1' },
  answer: Answer { idAnswer: '1', answer: 'bla' },
  options: [ Option { idOption: '1', option: 'ble' } ] }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...