簡體   English   中英

Angular 2調用多個異步方法

[英]Angular 2 calling multiple async methods

我有一個移動應用程序我正在構建,現在我正在進行身份驗證。 在我訪問主頁之前,我需要在我可以向用戶顯示數據之前,在我構建的API上點擊各種端點。

在Postman中測試時,所有端點都返回正確的數據,但是當我在我的應用程序中使用它時,我在第二次異步調用中得到一個null值。

我確定它與這些調用的順序有關,所以我只是在尋找一些幫助,以便我可以在啟動另一個調用之前等待一個調用完成。

public login() {

this.showLoading();

this.userService.getUserIdFromUserName(this.registerCredentials.username) // WORKS
  .subscribe(
    res => {
      console.log(res);
      localStorage.setItem("UserId", res.toString());
    },
    err => {
      console.log(err);
    });

this.userService.getEmployeeIdFromUserId(localStorage.getItem("UserId")) // THIS RETURNS NULL 
  .subscribe(
    res => {
      console.log(res);
      localStorage.setItem("EmployeeId", res.toString());
    },
    err => {
      console.log(err);
    });

this.authService.login(this.registerCredentials)
  .subscribe(

    data => {
      this.loading.dismissAll();
      console.log('User logged in successfully! ', data);
      this.nav.push(TabsPage);
      localStorage.setItem("Username", this.registerCredentials.username);
      localStorage.setItem("isLoggedIn", "true");
    },

    error => {
      this.loading.dismissAll();
      this.showAlert("Uh oh!", "Something went wrong. Please re-enter your login credentials or check your connection.");
      console.log(error);
    });
  }

您的原始代碼有一個導致此錯誤的錯誤。 您的代碼中有三個調用我將稱之為A),B)和C):

A) this.userService.getUserIdFromUserName(this.registerCredentials.username) // WORKS

B) this.userService.getEmployeeIdFromUserId(localStorage.getItem("UserId")) // THIS RETURNS NULL 

C) this.authService.login(this.registerCredentials)

關於RXJS需要了解的是 Observable(表示啟動異步操作所需的所有信息)和hot Observable(具有異步操作已啟動的Observable)之間的區別。

三個調用A),B)和C)只是構建冷可觀察對象,這些可觀察對象在你調用它們時會啟動.subscribe() 因此,當B)建成時,A)已經開始但還沒有完成。 因此,對localStorage.getItem("UserId")的調用將返回null,因為A)尚未調用其訂閱者的next回調。

所以你想要做的是B)等待A)。 而不是將某些內容填充到全局狀態(localStorage)中,最好將結果從A)流向B)。 輸入.mergeMap()運算符:

this.userService.getUserIdFromUserName(this.registerCredentials.username) // WORKS
  .map(res => res.toString())
  .do(userId => localStorage.setItem("UserId", userId)) // cleanly separate side-effects into .do() calls
  .mergeMap(userId => this.userService.getEmployeeIdFromUserId(userId))
  .map(res => res.toString())
  .do(employeeId => localStorage.setItem("EmployeeId", employeeId))
  .subscribe(
    employeeId => {
      console.log(employeeId);      
    },
    err => {
      console.log(err);
    });

關於rxjs的好處是錯誤處理只能在Observable鏈中一直工作。 如果您可以並行執行C),請查看.forkJoin()

最后,如果您需要親自解釋.mergeMap()查看以下答案: #ngrx示例中的SwitchMap與MergeMap

這應該工作。別忘了import 'rxjs/Rx'

this.userService.getUserIdFromUserName(this.registerCredentials.username)
  .map(res => res.toString())
  .do(userId => {
      console.log(res);
      localStorage.setItem("UserId", userId);
    })
  .flatMap(userId => {
       return this.userService.getEmployeeIdFromUserId(userId);
     })
  .do(res => {
      console.log(res);
      localStorage.setItem("EmployeeId", res.toString());
    })

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM