未捕获(承诺):FirebaseError

Uncaught (in promise): FirebaseError

我收到以下错误。我的问题是 NOT 实际错误,但事实上它说错误是 Uncaught。如果您查看我的 auth.service.tssign-in.component.ts 文件,我发现了错误。

我的问题是,为什么在控制台中出现 错误:未捕获(承诺) 错误?我错过了什么?

我正在使用
"@angular/fire": "^7.0.4"
"firebase": "^9.0.2"
"rxjs": "6.6.7"

auth.service.ts

    /**
     * Sign in
     *
     * @param credentials
     */
    signIn(credentials: { email: string; password: string }): Promise<any> 
    {
        return this.auth.signInWithEmailAndPassword(credentials.email, credentials.password)
            .then((userCredential) => {
                
                // Signed in 
                const user = userCredential.user;
                //console.log(user);

                // Store the access token in the local storage
                userCredential.user.getIdToken().then(token => {
                    this.accessToken = token;
                    //console.log(token);
                })

                // Set the authenticated flag to true
                this._authenticated = true;

                // Store the user on the user service
                //this._userService.user = user;

                // ...
            })
            .catch((error) => {
                const errorCode = error.code;
                const errorMessage = error.message;
                console.log('Show Error', error.code);
                throw errorCode;
            });
    }

符号-in.component.ts

    /**
     * Sign in
     */
    signIn(): void
    {
        // Return if the form is invalid
        if ( this.signInForm.invalid )
        {
            return;
        }

        // Disable the form
        this.signInForm.disable();

        // Hide the alert
        this.showAlert = false;

        // Sign in
        this._authService.signIn(this.signInForm.value)
            .then(
                () => {

                    // Set the redirect url.
                    // The '/signed-in-redirect' is a dummy url to catch the request and redirect the user
                    // to the correct page after a successful sign in. This way, that url can be set via
                    // routing file and we don't have to touch here.
                    const redirectURL = this._activatedRoute.snapshot.queryParamMap.get('redirectURL') || '/signed-in-redirect';

                    // Navigate to the redirect url
                    this._router.navigateByUrl(redirectURL);

                },
                (response) => {

                    console.log('error from auth.service', response);

                    // Re-enable the form
                    this.signInForm.enable();

                    // Reset the form
                    this.signInNgForm.resetForm();

                    // Set the alert
                    this.alert = {
                        type   : 'error',
                        message: 'Wrong email or password'
                    };

                    // Show the alert
                    this.showAlert = true;
                }
            );
    }

正如 Frank 提到的那样,您抛出了一个错误而没有在更高的级别上将其捕获回来,我会尝试这样做:

try {
  this._authService.signIn(this.signInForm.value)
            .then(
                () => {

                    // Set the redirect url.
                    // The '/signed-in-redirect' is a dummy url to catch the request and redirect the user
                    // to the correct page after a successful sign in. This way, that url can be set via
                    // routing file and we don't have to touch here.
                    const redirectURL = this._activatedRoute.snapshot.queryParamMap.get('redirectURL') || '/signed-in-redirect';

                    // Navigate to the redirect url
                    this._router.navigateByUrl(redirectURL);

                },
                (response) => {

                    console.log('error from auth.service', response);

                    // Re-enable the form
                    this.signInForm.enable();

                    // Reset the form
                    this.signInNgForm.resetForm();

                    // Set the alert
                    this.alert = {
                        type   : 'error',
                        message: 'Wrong email or password'
                    };

                    // Show the alert
                    this.showAlert = true;
                }
            );
} catch(e) {}

只需用 try catch 块将您的代码包围起来,这样错误就会消失。我没有测试它,但也许在 then 之后调用另一个 catch 方法仍然可以达到相同的水平(Promise 水平),所以我不确定它是否有效。

首先,我的母语不是英语,所以如果我写得像个傻子,你知道为什么。

试试这个:

_authService.service.ts

    import { getAuth, signInWithEmailAndPassword, Auth, inMemoryPersistence, browserLocalPersistence } from '@angular/fire/auth';


    constructor(private _fireAuth: Auth,) {

/**
 * Sign-in
 *
 * @param credentials
 * @param rememberMe
 */
    async signIn(credentials: { email: string; password: string }, rememberMe: boolean): Promise<any> {
        // firebase Persistence.LOCAL   browserLocalPersistence
        // firebase Persistence.SESSION browserSessionPersistence
        // firebase Persistence.NONE    inMemoryPersistence

        return new Promise(async (resolve, reject) => {
            //Initialize auth()
            const auth = getAuth();

            // Extra function
            if (rememberMe) {
                await getAuth().setPersistence(browserLocalPersistence).catch(error => reject(-1));
            } else {
                await getAuth().setPersistence(inMemoryPersistence).catch(error => reject(-1));
            }

            signInWithEmailAndPassword(auth, credentials.email, credentials.password).then(async (userCredential) => {
                // Signed in 
                const user = userCredential.user;
                console.log(user);

                // Store the access token in the local storage
                await userCredential.user.getIdTokenResult().then(token => {
                    this.accessToken = token.token;
                    console.log(token);
                })

                // Set the authenticated flag to true
                this._authenticated = true;
            }).catch(error => reject(error.code));
        });
    }

注意:如你所见,我添加了一些额外的功能,如果你不感兴趣,你可以将其删除(setPersistence),这可以让你考虑到用户的选择如果他想保持登录状态,或者在他关闭选项卡时删除他的登录信息。

符号-in.component.ts

alert = {
        userNotFound : false,
        wrongPassword: false,
        unknownError : false,
};
    /**
     * Sign in
     */
    signIn(): void
    {
        // Return if the form is invalid
        if ( this.signInForm.invalid )
        {
            return;
    }

    // Disable the form
    this.signInForm.disable();

    // Hide the alert
    this.showAlert = false;

    // Sign in
    this._authService.signIn(this.signInForm.value)
        .then(
            () => {

                // Set the redirect url.
                // The '/signed-in-redirect' is a dummy url to catch the request and redirect the user
                // to the correct page after a successful sign in. This way, that url can be set via
                // routing file and we don't have to touch here.
                const redirectURL = this._activatedRoute.snapshot.queryParamMap.get('redirectURL') || '/signed-in-redirect';

                // Navigate to the redirect url
                this._router.navigateByUrl(redirectURL);

            },
            (response) => {

                console.log('error from auth.service', response);

                // Re-enable the form
                this.signInForm.enable();

                // Reset the form
                this.signInNgForm.resetForm();

                // Set the alert
                if (error === - 1) {
                this.alert.unknownError = true;
                } else if (error === 'auth/email-not-found' || error === 'auth/user-not-found') {
                this.alert.userNotFound = true;
                } else if (error === 'auth/wrong-password') {
                this.alert.wrongPassword = true;
                }
            }
        );
}

对我来说,明确地 catch 上述答案中的错误仍然导致错误作为 Uncaught (in Promise) 发送到控制台。无论出于何种原因,除了通过 Promise.catch 发送要捕获的错误外,Angular 还通过其默认值 ErrorHandler and claiming that the error was uncaught. I had to override the default ErrorHandler with my own, detect that these were FirebaseErrors 路由错误,然后忽略它们(因为我已经有一个明确的 Promise.catch 在我需要的地方定义。

一些有用的提示:

  1. Angular 只识别在 root 模块上定义的错误处理程序。 child 模块的定义似乎被忽略了。您将获得一个需要执行所有操作的全局错误处理程序。
  2. 核心 FirebaseErrors 似乎存储在主 error 对象的 rejection 属性 中。您可以像这样检测它们:
import { ErrorHandler, Injectable } from "@angular/core";
import { FirebaseError } from "firebase/app";

interface AngularFireError extends Error {
    rejection: FirebaseError;
}

function errorIsAngularFireError(err: any): err is AngularFireError {
    return err.rejection && err.rejection.name === 'FirebaseError';
}

// Not providedIn 'root': needs special handling in app.module to override default error handler.
@Injectable()
export class YourErrorHandler implements ErrorHandler {
    handleError(error: any) {
        // AngularFire errors should be catchable and handled in components; no need to further process them.
        if (!errorIsAngularFireError(error)) {
            console.error(error);
        }
    }
}

在你的根模块中:

providers: [
    ...,
    { provide: ErrorHandler, useClass: YourErrorHandler }
  ],