我正在开发一个移动应用程序,现在我正在进行身份验证。在我访问我的主页之前,我需要访问我构建的API上的各种endpoint,然后才能向用户显示数据。
在Postman中测试时,所有endpoint都返回了正确的数据,但是当我在应用程序中使用它时,我在第二次异步调用中得到了一个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);
});
}
这应该行得通。别忘了导入'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());
})
您的原始代码存在导致此错误的错误。您的代码中有三个调用,我称之为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,您需要了解的是冷可观察(表示启动异步操作所需的所有信息)和热可观察(已启动异步操作的可观察)之间的区别。
这三个调用A)、B)和C)仅构建冷的可观察对象,这些可观察对象在调用时就开始了。在它们上订阅()。因此,在B)构建时,A)已经开始,但尚未完成。因此,调用
localStorage。getItem(“UserId”)
将返回null,因为A)尚未调用其订阅者的next
回调。
所以你想做的是让B)等待A)。此外,与其将某物填充到全局状态(本地存储),不如将结果从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的好处在于,错误处理在可观察链中始终有效。如果可以并行执行C),请查看
。forkJoin()
。
最后,如果您需要
的实际解释。mergeMap()
看看这个答案:在#ngrx示例中,SwitchMap与mergeMap
当导航到带有防护装置的页面时,已或都会打印到控制台(在等待 firebase 响应的一段时间后)。但是,导航永远不会完成。另外,如果我没有登录,我会被重定向到路由。因此,我遇到的问题是 不会向用户显示请求的页面。我假设这是因为我正在使用回调,但我无法弄清楚如何做到这一点。有什么想法吗?
我调用了多个ajax调用,但代码只在所有ajax调用执行之后才到达API。 JavaScript: AppFactory API 链接工作很好,但我需要运行两个独立,我真的想知道发生了什么。 谢谢!!!
问题内容: 我使用的是Spring 4,我注意到了一个奇怪的行为……如果我从普通实例方法多次调用异步方法,那么它们都将在不同的线程中调用,并在随机时间完成。但是,如果我多次从另一个异步方法中调用一个异步方法,那么它们将按顺序完成。我有这样的事情: 我正在使用默认的异步执行器。我应该换一个吗?但是,该执行程序不会重用任何线程,而是每次都启动另一个线程,因此应该没问题……这仅仅是巧合吗?但是我尝试了十
同步调用异步方法最安全的方法是什么?
我正试图从同步方法运行异步方法。但是我不能等待异步方法,因为我在同步方法中。我一定不理解TPL,因为这是我第一次使用它。 每个方法都需要前一个方法来完成,因为第一个方法的数据用于第二个方法。 Await运算符只能在异步方法中使用。考虑用'async'修饰符标记此方法,并将其返回类型更改为'task' 但是,如果我使用async修饰符,这将是一个异步操作。因此,如果我对的调用没有使用await运算符