Patryk
Patryk

Reputation: 1207

Angular RxJS Subscribe to HTTP Request in HTTP Request

I want to make a singup function to get a token. Function should work like that:

  1. First I have to make a HTTP POST request passing login value to get "nonce" string
  2. Second, after first is done, when I have already "nonce" string, I have to make another HTTP POST request with login value and password encrypted like SHA256(SHA256(password) + nonce))

I have a singup ractive form, and my on click button "onLogin" function use a service "singup(login, password)" function which return an observable to check if requests are done well (or not).

So I wonder how to properly implement sequence of requests to return to onLogin() function information (as observable) if one the one of them (requests) failed (i want to know if getNonce or login return error).

Auth Service:

  singup(login: string, password: string) {
    return this.getNonce(login).subscribe(result => {
      const nonce = result.nonce; 
      return this.login(login, password, nonce); 
    });
  };

  login(login: string, password: string, nonce: string | undefined): Observable<any> {
    return this.http.post<any>(`${this.config.url}/user/login`, {
      login: login,
      password: sha256(sha256(password) + nonce)
    });
  };

  getNonce(login: string) {
    return this.http.post<{ nonce: string }>(`${this.config.url}/user/login`, {
      login: login
    });
  }

FormClass

onLogin() {
    this.authService.singup(this.singupForm.value.login, this.singupForm.value.password).subscribe(result => {
      // steps after get token or not
    });
  }

I will be thankful for good advices.

Upvotes: 0

Views: 590

Answers (1)

Amit Beckenstein
Amit Beckenstein

Reputation: 1332

To add on @wadie's suggestion (and correct answer), the reason why you should use switchMap() (you could also use concatMap(), they'd both work) is because it turns both Observables into a single one - it's what's called a Higher-order Observable. This Observable will emit values or errors from any of the inner Observables, which is what you want to achieve. This will also mean that you'll only need to subscribe() once for the entire Observable chain.

Also, your current code shouldn't work - login() is called inside signup(), but the login request will not fire because Observables are not "activated" until you subscribe(), and you don't subscribe() to login(). You could indeed call subscribe() inside that other subscribe(), but then you wouldn't be able to clean that Subscription easily. Higher-order Observable solve that by combining the subscriptions to all the inner Observables into a single one.

Upvotes: 2

Related Questions