如何在Angular中进行嵌套订阅?

时间:2020-06-07 06:35:55

标签: angular typescript

你好,我有一个嵌套订阅,我以下面的方式处理,听说这是一个不好的方法。

有人可以让我知道最好的方法吗?它将真的帮助我学习。下面是我的代码,请看看。 TIA

login.ts

 login(email: string, password: string) {
    const user = new FormData();
    user.append("username", email);
    user.append("password", password);
    this.http
      .post<any>("api1", user)
      .subscribe((response) => {
        this.myToken = response.access_token;
        console.log(this.myToken);
        if (this.myToken) {
          const body = new HttpParams()
            .set("username", email)
            .set("password", password);

          return this.http
            .post<any>("api2", body, {
              headers: new HttpHeaders({
                "Content-Type": "application/x-www-form-urlencoded",
                Authorization: `${this.myToken}`,
              })
            })
            .subscribe((response) => console.log(response));
        } else {
          alert("error: Not authorized");
        }
      });
  }

2)加载组件后,我需要检查我的get api响应。如果我得到get API response == null,则需要使用相同的表单发布数据。当我获得API response != null时,我需要将值修补到表单,并且应该能够使用PUT API

更新

form.ts

 getVal() {
      http.get<any>(API).subscribe(response => {
       this.getResponse= response;
       if (this.getResponse != null) {
          this.form.patchValue({.     //append the values to the form
            username: response.username,
          })

      })
    }

   onRegisterSubmit(form) {
   this.username = form.value
   console.log(form.value);
    if (this.getResponse != null) {
       //I want to enable update button and update api here
          http.put<any>(api, this.username).subscribe(resposne => 
          console.log(response) )
        } if(response == null) {
           http.post<any>(api, this.username).subscribe(resposne => 
          console.log(response) )
        //I want to send data using post method.
        }
 }

2 个答案:

答案 0 :(得分:1)

嵌套订阅是不好的,因为会有多个没有直接依赖性的订阅,这将导致更多潜在的内存泄漏。您需要使用RxJS高阶运算符(例如switchMap)来组合多个可观察对象。尝试以下

import { EMPTY } from 'rxjs';
import { switchMap } from 'rxjs/operators';

login(email: string, password: string) {
  const user = new FormData();
  user.append("username", email);
  user.append("password", password);
  this.http.post<any>("api1", user).pipe(
    switchMap((response) => {
      this.myToken = response.access_token;
      console.log(this.myToken);
      if (this.myToken) {
        const body = new HttpParams().set("username", email).set("password", password);
        const headers = new HttpHeaders({
          "Content-Type": "application/x-www-form-urlencoded",
          Authorization: `${this.myToken}`
        });
        return this.http.post<any>("api2", body, { headers: headers });
      } else {
        alert("error: Not authorized");
        return EMPTY;
      }
    })
  ).subscribe(
    (response) => { console.log(response) },
    (error) => { }
  );
}

更新-错误

onRegisterSubmit()函数中,我们检查this.getResponse变量是否已定义,但在getVal()函数中异步为其分配了一个值。

onRegisterSubmit(form) {
  this.username = form.value;
  console.log(form.value);
  if (this.getResponse) {         // <-- implies `this.getResponse` is already assigned in `onRegisterSubmit()` function
    http.put<any>(api, this.username).pipe(
      switchMap(putResponse => {
        console.log(putResponse);
        if(!putResponse) {
          return http.post<any>(api, this.username);
        }
        return EMPTY;
      })
    ).subscribe(
      postResponse => { console.log(Postresponse) },
      error => { }
    );
  }
}

switchMap()运算符应返回一个可观察值。因此,如果没有可观察到的返回值,则可以使用RxJS EMPTY常量。它创建一个可观察对象,并立即发出完整的通知。

更新2

要有条件地订阅一个可观察对象,可以使用RxJS iif方法。

onRegisterSubmit(form) {
  this.username = form.value;
  console.log(form.value);
  iif(() => 
    this.getResponse,
    http.put<any>(api, this.username),
    http.post<any>(api, this.username)
  ).subscribe(
    respone => { console.log(response) },
    error => { }
  );
}

答案 1 :(得分:0)

您的最后一个疑问。您不需要包装Put,因为this.getResponse是不可观察的值,因此使用if and else条件比使用任何Rxjs运算符更好。使用if and else不是onRegisterSubmit method的嵌套订阅。

或者您可以像使用它

onRegisterSubmit(form) {
 this.username = form.value;
  iif(() => 
    this.getResponse,
    http.put<any>(api, this.username),
    http.post<any>(api, this.username)
  ).subscribe(
    respone => { console.log(response) },
    error => { }
  );
}