在Bootstrap-Modal中捕获Firebase错误

时间:2017-01-24 15:19:53

标签: twitter-bootstrap angular authentication firebase error-handling

我刚刚使用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">&times;</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());
          });
    }
}

控制台抛出这些错误:

errors_chrome_console

我认为这两行有问题:

this.errorService.handleError(error.json());
return Observable.throw(error.json());

,因为

console.log(error)

不会抛出任何错误,只会在控制台中记录错误。

我还尝试过herehere的代码:

.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

我做错了什么?或者我错过了什么?

1 个答案:

答案 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:)