我刚刚使用Angular 2和Firebase完成了自己的Login-Signup-App,但是我对#34;正确"错误处理
我的Angular 2 App结构如下:
| app.component.css
| app.component.html
| app.component.ts
| app.module.ts
| app.routing.ts
| index.ts
|
+---errors
| error.component.html
| error.component.ts
| error.model.ts
| error.service.ts
|
+---protected
| protected.component.ts
| protected.guard.ts
|
+---shared
| auth.service.ts
| header.component.ts
| index.ts
| user.interface.ts
|
\---unprotected
signin.component.ts
signup.component.ts
我的整个应用程序工作正常,但我现在想要捕获FirebaseErrors并将其显示在Bootstrap模态中。
我创建了一个errorService,一个errorModel和一个errorComponent。我试过以下:
首先,我在 error.model.ts 中定义了一个Error类
export class Error {
constructor(public title: string, public message: string) {}
}
然后我设置了 error.component.ts
export class ErrorComponent implements OnInit{
error: Error;
display = 'none';
constructor(private errorService: ErrorService) {}
onErrorHandled() {
this.display = 'none';
}
ngOnInit() {
this.errorService.errorOccurred.subscribe(
(error: Error) => {
this.error = error;
this.display = 'block';
}
);
}
}
使用 error.component.html
<div class="backdrop" [ngStyle]="{'display': display}"></div>
<div class="modal" tabindex="-1" role="dialog" [ngStyle]="{'display': display}">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="onErrorHandled()"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">{{ error?.title }}</h4>
</div>
<div class="modal-body">
<p>{{ error?.message }}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" (click)="onErrorHandled()">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
现在,当我想捕捉 auth.service.ts
中的错误时declare var firebase: any;
@Injectable()
export class AuthService {
constructor(private router: Router, private errorService: ErrorService) {}
signupUser(user:User) {
firebase.auth().createUserWithEmailAndPassword(user.email, user.password)
.catch(function (error) {
this.errorService.handleError(error.json());
return Observable.throw(error.json());
});
}
signinUser(user:User) {
firebase.auth().signInWithEmailAndPassword(user.email, user.password)
.catch(function (error) {
this.errorService.handleError(error.json());
return Observable.throw(error.json());
});
}
}
控制台抛出这些错误:
我认为这两行有问题:
this.errorService.handleError(error.json());
return Observable.throw(error.json());
,因为
console.log(error)
不会抛出任何错误,只会在控制台中记录错误。
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
}
但仍然没有运气。
我实际上想要从控制台显示此错误日志:
{code: "auth/email-already-in-use", message: "The email address is already in use by another account."}
到正常的Bootstrap-Modal
我做错了什么?或者我错过了什么?
答案 0 :(得分:2)
首先,在你的auth.service.ts
中,你在catch函数中丢失了上下文,这就是你得到错误的原因。您可以使用arrow functions:
declare var firebase: any;
@Injectable()
export class AuthService {
constructor(private router: Router, private errorService: ErrorService) {}
signupUser(user:User) {
firebase.auth().createUserWithEmailAndPassword(user.email, user.password)
.catch((error) => {
this.errorService.handleError(error.json());
return Observable.throw(error.json());
});
}
signinUser(user:User) {
firebase.auth().signInWithEmailAndPassword(user.email, user.password)
.catch((error) => {
this.errorService.handleError(error.json());
return Observable.throw(error.json());
});
}
}
现在,当捕捉到错误时,errorService
的方法将被调用。我不知道你的错误服务如何实现,但一种方法是设置一个Subject属性,如下例所示:
@Injectable()
export class ErrorService{
public errorOccurred: Subject<Error>;
constructor(){
this.errorOccurred = new BehaviorSubject<Error>(null);
}
handleError(error) {
this.errorOccurred.next(error); //pass next value to subject
}
}
使用此设置,您将能够立即获得错误组件错误:
export class ErrorComponent implements OnInit{
error: Error;
display = 'none';
constructor(private errorService: ErrorService) {}
onErrorHandled() {
this.display = 'none';
}
ngOnInit() {
this.errorService.errorOccurred.subscribe(
(error: Error) => {
if (error !== null) {
this.error = error;
this.display = 'block';
}
}
);
}
}
此方法的唯一缺点是您需要将错误组件保留在模板中。解决方案是设置组件工厂并仅在发生错误时将模式注入模板。如果你需要,我可以设置一个plnkr:)