Firebase 身份验证:无效的电子邮件地址导致 node.js (Express) 应用程序崩溃

Phi*_*umi 5 node.js express firebase firebase-authentication

我这里有一个奇怪的问题。简单代码:

router.post("/resetpassword/:email", async (req, res) => {
    try {
        var auth = firebase.auth();
        await auth.sendPasswordResetEmail(req.params.email);
        res.sendStatus(200);
    } catch (e) {
        console.log(e);
        res.sendStatus(400);
    }
});
Run Code Online (Sandbox Code Playgroud)

这段代码工作正常,如果

  • 电子邮件有效且已知
  • 电子邮件未知(我收到一个我可以处理的状态代码的异常)

但是如果电子邮件格式错误,我也会收到状态代码异常,但是在调用 catch 块后我的 Express 应用程序崩溃。HTTP 400 被发送到客户端,但在那之后,我的应用程序已经死了。

这是控制台输出。第一个块用于未知电子邮件地址,第二个块用于格式错误的电子邮件地址。

{ [Error: There is no user record corresponding to this identifier. The user may have been deleted.]
  code: 'auth/user-not-found',
  message: 'There is no user record corresponding to this identifier. The user may have been deleted.' }



{ [Error: The email address is badly formatted.]
  code: 'auth/invalid-email',
  message: 'The email address is badly formatted.' }

[...]\node_modules\firebase\auth-node.js:39
h.send=function(a){if(a)if("string"==typeof a)this.sa.send(a);else throw Error("Only string data is supported");else this.sa.send()};h.abort=function(){this.sa.abort()};h.setRequestHeader=function(){};h.He=function(){this.status=200;this.responseText=this.sa.responseText;Ic(this,4)};h.Jd=function(){this.status=500;this.responseText="";Ic(this,4)};h.Je=function(){this.Jd()};h.Ie=function(){this.status=200;Ic(this,1)};var Ic=function(a,b){a.readyState=b;if(a.onreadystatechange)a.onreadystatechange()};var Jc=function(a,b,c){this.Ue=c;this.we=a;this.kf=b;this.oc=0;this.gc=null};Jc.prototype.get=function(){var a;0<this.oc?(this.oc--,a=this.gc,this.gc=a.next,a.next=null):a=this.we();return a};Jc.prototype.put=function(a){this.kf(a);this.oc<this.Ue&&(this.oc++,a.next=this.gc,this.gc=a)};var Kc=function(a){l.setTimeout(function(){throw a;},0)},Lc,Mc=function(){var a=l.MessageChannel;"undefined"===typeof a&&"undefined"!==ty
Error: The email address is badly formatted.
[nodemon] app crashed - waiting for file changes before starting...
Run Code Online (Sandbox Code Playgroud)

我目前认为这是我的一个愚蠢的错误(我对 node/Express 还很陌生)。知道我在这里缺少什么吗?

Mic*_*ral 5

我自己在与firebase.auth()自己合作时遇到了这个错误,确实很奇怪。我认为这firebase.auth()似乎使用了它自己的 Promise 变体,如果该 Promise 没有捕获错误,或者甚至在链接到它/ 中抛出错误,它就会使您的应用程序崩溃.then.catch

这是我制作的一个小函数,它确保将被拒绝的承诺转换为已解决的承诺,然后再将其转换为被拒绝的承诺。这防止了我的应用程序崩溃,但我找不到更简单的方法。

let firebase_auth_wrap = async (promise) => {
  let rejected = Symbol();
  let value_or_error = await promise.catch((error) => {
    return { [rejected]: true, error: error };
  });

  if (value_or_error[rejected]) {
    throw value_or_error.error;
  } else {
    return value_or_error;
  }
}

...

let { uid } = await firebase_auth_wrap(firebase.auth().signInWithEmailAndPassword(email, password));
Run Code Online (Sandbox Code Playgroud)

希望它也适用于您,如果可以更直观地完成,请告诉我:)


rsp*_*rsp 0

当你运行这个时:

await auth.sendPasswordResetEmail(req.params.email);
Run Code Online (Sandbox Code Playgroud)

try在/块内部catch然后你处理两件事:

  1. 立即抛出auth.sendPasswordResetEmail()异常
  2. 拒绝auth.sendPasswordResetEmail()返回的承诺

您不处理的是,当代码的其他部分发生某些情况并抛出未被任何内容捕获的异常时。

当然,当您发布指向包含数千个字符的行的错误消息的示例时,不可能告诉您在您的情况下发生了什么,但这是一个简单的示例。

在此示例中,您将捕获被拒绝的 Promise:

let f = () => new Promise((res, rej) => {
  rej(new Error('Error'));
});
(async () => {
  try {
    let x = await f();
    console.log('Returned value:', x);
  } catch (e) {
    console.log('Handled error:', e.message);
  }
})();
Run Code Online (Sandbox Code Playgroud)

在此示例中,您将捕获抛出的异常:

let f = () => new Promise((res, rej) => {
  throw new Error('Error');
});
(async () => {
  try {
    let x = await f();
    console.log('Returned value:', x);
  } catch (e) {
    console.log('Handled error:', e.message);
  }
})();
Run Code Online (Sandbox Code Playgroud)

在此示例中,您将处理事件循环的不同滴答中发生的拒绝:

let f = () => new Promise((res, rej) => {
  setImmediate(() => rej(new Error('Error')));
});
(async () => {
  try {
    let x = await f();
    console.log('Returned value:', x);
  } catch (e) {
    console.log('Handled error:', e.message);
  }
})();
Run Code Online (Sandbox Code Playgroud)

但在本例中,您将不会处理事件循环的不同滴答处抛出的异常:

let f = () => new Promise((res, rej) => {
  setImmediate(() => { throw new Error('Error'); });
});
(async () => {
  try {
    let x = await f();
    console.log('Returned value:', x);
  } catch (e) {
    console.log('Handled error:', e.message);
  }
})();
Run Code Online (Sandbox Code Playgroud)

你的情况一定会发生类似的事情。