[英]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.