-1

I want to use data from the first subscribe in the second subscribe. I received response, that have field 'article', and after I have received it, I should do another request to set article.author value.

    if (!this.article) {

        this.articleSubscription = this.route.paramMap
            .pipe(
                switchMap(params => {
                    this.isLoadingInProgress = true;
                    return this.dataService.getArticleById(params.get('id'));
                }),
            ).subscribe(response => {
                this.article = response.currentArticle;
                this.article.relatedArticles = response.relatedArticles;

                this.userService.getAllUsers$().subscribe(users => {
                    const author: AlArticleAuthor =
                        users.find(user => user.id === this.article.userId);
                    this.article.author = {
                        firstName: author.firstName,
                        lastName: author.lastName,
                        organization: author.organization,
                        title: author.title,
                    };
                });
                this.isLoadingInProgress = false;
                super.setTitle(this.article.title);
                super.setMetaDescription(this.article.description);
                this.changeDetection.markForCheck();
            });
    }
prolina
  • 185
  • 4
  • 14
  • 1
    Does this answer your question? [Angular Subscribe within Subscribe](https://stackoverflow.com/questions/55447803/angular-subscribe-within-subscribe) – wentjun Jun 12 '20 at 19:37

2 Answers2

0

The answer is already in the question. You just need to use an additional switchMap. Try the following

if (!this.article) {
  this.articleSubscription = this.route.paramMap.pipe(
    take(1),     // <-- use the first notification and complete
    switchMap(params => {
      this.isLoadingInProgress = true;
      return this.dataService.getArticleById(params.get('id')).pipe(
        switchMap(article => {     // <-- map the 1st API observable to 2nd API observable
          this.article = article.currentArticle;
          this.article.relatedArticles = article.relatedArticles;
          return this.userService.getAllUsers$();
        })
      )
    })
  ).subscribe(users => {
      const author: AlArticleAuthor = users.find(user => user.id === this.article.userId);
      this.article.author = {
        firstName: author.firstName,
        lastName: author.lastName,
        organization: author.organization,
        title: author.title,
      };
    },
    error => {
      // handle error
    },
    () => {     // <-- `complete` callback - executed when the HTTP request is complete
      this.isLoadingInProgress = false;
      super.setTitle(this.article.title);
      super.setMetaDescription(this.article.description);
      this.changeDetection.markForCheck();
    }
  );
}
ruth
  • 29,535
  • 4
  • 30
  • 57
  • Thank you for your answer, I tried to realize it, but have problem that `this.isLoadingInProgress` is true, and on UI I have a spinner. – prolina Jun 12 '20 at 10:31
  • and also sometimes users is not array, it's just one of the array objects – prolina Jun 12 '20 at 10:35
  • Q1. Showing spinner when `this.isLoadingInProgress = true` doesn't sound logically wrong to me. Q2. Please update the question with some example data on what you mean. – ruth Jun 12 '20 at 10:38
  • code into 'complete' callback doesn't call, I added console.log. – prolina Jun 12 '20 at 14:12
  • Yes the `paramMap` is a stream. Pipe in a `take(1)` to use only the first emission and complete. I've modified the answer. I assume `this.userService.getAllUsers$()` is an HTTP call, if not you need to pipe in a `take(1)` to it as well. – ruth Jun 12 '20 at 14:57
  • I added `take(1)` but in this case if route is changed (if I for example click on related articles) on UI I have the same article but in url - correct. – prolina Jun 12 '20 at 16:28
0

use mergeMap. It is very useful to send one api data to another api data. I attached working screenshot of the code. Don't forget it to import mergeMap from rxjs. Cheers!!

map(users => {
const user = users[0];
return user;
}),
mergeMap(user=> this.http.get(`https://secondapicall.com?userId=${user.id}`))).subscribe(posts=> {console.log(posts)});```
Ravi Badoni
  • 87
  • 2
  • 5
  • 1
    Please, [do not include screenshots of code](https://meta.stackoverflow.com/questions/382026/how-should-i-review-answers-with-screenshots-of-code-in-low-quality-posts). They're difficult to read, they prevent users from copying the code, and they prevent search engines from helping people with similar problems find this post. Please edit your answer to include the code inline. Stack Overflow includes the ability to place code within a code block (e.g., by indenting it by four spaces). – Jeremy Caney Jun 13 '20 at 00:50