http.post 订阅从服务到组件的链接错误
Error chaining from a service to component for a http.post subscription
我正在使用 firebase 对登录进行身份验证,然后向我的后端发送请求,为登录用户创建自定义会话令牌。为此,我将函数调用从 component.ts 发送到 service.ts。
SignIn(email: string, password: string) {
return this.angularFireAuth
.signInWithEmailAndPassword(email, password)
.then(async res => {
const idToken = await res.user.getIdToken()
this.http.post(environment.baseURL + "auth/sessionLogin", { idToken: idToken }).pipe(
catchError(err=>{
return throwError("FailedLogin") // ** NOT USEFUL ERROR
})
)
.subscribe((response) => {
this.router.navigate(["/signup"]); // ** IF SIGN IN IS SUCCESSFUL
}
// , (err) => {
// throw new Error("Failed Login"). // ** NOT USEFUL ERROR
// }
)
return { loggedIn: false, message: "Failed Login" } // ** INCASE MY BACKEND THROWS ERROR
}).catch(err => {
return { loggedIn: false, message: err.message }. // ** INCASE FIREBASE THROWS ERROR
});
}
component.ts代码是
async signIn(loginF: NgForm) {
const email = loginF.value.email
const password = loginF.value.password
const response = await this.authenticationService.SignIn(email, password)
if(!response.loggedIn){
// my error handling code for flash messages
}
}
现在,上面的代码完成了工作,但我知道这是最糟糕的错误处理方式之一,因为我没有充分利用可观察对象的潜力。我想知道如何使用 catchError 或 try-catch 块来不手动发送和检查自定义 { loggedIn: false, message: err.message } like object to my组件。
上面的 catchErrors 基本上没有用,因为它们没有被转发到我的组件。如果我 return this.http.post..,它说这是一个订阅,我不能在上面做 .then() + 它说 response 在我的前端将是订阅类型或类型 { loggedIn: false, message: err.message }
更新:一个可能的答案
我已经分解了两件事:使用 firebase 登录,然后将令牌请求发送到后端分为两个不同的部分。它看起来是一个更优雅的解决方案,因为它不涉及任何手动响应对象创建。
** component.ts**
async signIn(loginF: NgForm) {
const email = loginF.value.email
const password = loginF.value.password
let idToken
try{
idToken = await this.authenticationService.SignIn(email, password)
}catch(err){
idToken = null; // ** INCASE FIREBASE FAILS
// error handling for flash messages
}
if(idToken!= null){
this.authenticationService.SignInBackend(idToken).subscribe((response) => {
this.router.navigate(["/signup"]);
}
, (err) => {
// error handling for flash messages // ** INCASE BACKEND FAILS
}
)
}
}
** service.ts**
SignIn(email: string, password: string) {
return this.angularFireAuth
.signInWithEmailAndPassword(email, password)
.then(async res => {
const idToken = await res.user.getIdToken()
return idToken;
}).catch(err => {
throw new Error(err.message). // ** ERROR GETS CHAINED
});
}
SignInBackend(idToken){
return this.http.post(environment.baseURL + "auth/sessionLogin", { idToken: idToken })
}
我正在使用 firebase 对登录进行身份验证,然后向我的后端发送请求,为登录用户创建自定义会话令牌。为此,我将函数调用从 component.ts 发送到 service.ts。
SignIn(email: string, password: string) {
return this.angularFireAuth
.signInWithEmailAndPassword(email, password)
.then(async res => {
const idToken = await res.user.getIdToken()
this.http.post(environment.baseURL + "auth/sessionLogin", { idToken: idToken }).pipe(
catchError(err=>{
return throwError("FailedLogin") // ** NOT USEFUL ERROR
})
)
.subscribe((response) => {
this.router.navigate(["/signup"]); // ** IF SIGN IN IS SUCCESSFUL
}
// , (err) => {
// throw new Error("Failed Login"). // ** NOT USEFUL ERROR
// }
)
return { loggedIn: false, message: "Failed Login" } // ** INCASE MY BACKEND THROWS ERROR
}).catch(err => {
return { loggedIn: false, message: err.message }. // ** INCASE FIREBASE THROWS ERROR
});
}
component.ts代码是
async signIn(loginF: NgForm) {
const email = loginF.value.email
const password = loginF.value.password
const response = await this.authenticationService.SignIn(email, password)
if(!response.loggedIn){
// my error handling code for flash messages
}
}
现在,上面的代码完成了工作,但我知道这是最糟糕的错误处理方式之一,因为我没有充分利用可观察对象的潜力。我想知道如何使用 catchError 或 try-catch 块来不手动发送和检查自定义 { loggedIn: false, message: err.message } like object to my组件。
上面的 catchErrors 基本上没有用,因为它们没有被转发到我的组件。如果我 return this.http.post..,它说这是一个订阅,我不能在上面做 .then() + 它说 response 在我的前端将是订阅类型或类型 { loggedIn: false, message: err.message }
更新:一个可能的答案
我已经分解了两件事:使用 firebase 登录,然后将令牌请求发送到后端分为两个不同的部分。它看起来是一个更优雅的解决方案,因为它不涉及任何手动响应对象创建。
** component.ts**
async signIn(loginF: NgForm) {
const email = loginF.value.email
const password = loginF.value.password
let idToken
try{
idToken = await this.authenticationService.SignIn(email, password)
}catch(err){
idToken = null; // ** INCASE FIREBASE FAILS
// error handling for flash messages
}
if(idToken!= null){
this.authenticationService.SignInBackend(idToken).subscribe((response) => {
this.router.navigate(["/signup"]);
}
, (err) => {
// error handling for flash messages // ** INCASE BACKEND FAILS
}
)
}
}
** service.ts**
SignIn(email: string, password: string) {
return this.angularFireAuth
.signInWithEmailAndPassword(email, password)
.then(async res => {
const idToken = await res.user.getIdToken()
return idToken;
}).catch(err => {
throw new Error(err.message). // ** ERROR GETS CHAINED
});
}
SignInBackend(idToken){
return this.http.post(environment.baseURL + "auth/sessionLogin", { idToken: idToken })
}