QuerySnapshot.empty 导致承诺拒绝错误

问题描述

我有一个使用 firebase-admin 和 express 的后端,允许从客户端向服务器发送请求,以更改我拥有的包含用户数据等内容的 Firestore(这是一个测试,而不是真正的产品) .我想检查文档是否已经存在,以便用户无法再次使用该用户名进行注册。我第一次看到 doc.exists 的实例,但它为我返回 undefined,我查看了文档并找到了 doc.empty,据说它可以检查文档是否为空。我试过了,但它返回了一个承诺拒绝错误。如果我将该行更改为 .exists 或其他内容,那么问题就会消失,因此我已将问题范围缩小到该行。

index.js(后端)

app.post("/registeruser",function (req,res) {
    res.setHeader("Content-Type","application/json");

    try {
        const username = req.body.username;
        const password = req.body.password;
        const passwordEncrypted = HmacSHA1(password,JSON.parse(fs.readFileSync("./keys.json"))["passwordEncryptKey"]).toString();

        // console.log(username,password,passwordEncrypted);

        try {
            firestore.collection("users").get(username).then(function (data) {
                if (data.empty == false) {
                    throw [true,"Already registered user!"];
                }
            }).catch(function (error) {
                throw [true,error];
            });

            if (username == "") {
                firestore.collection("users").add({
                    username: v4(),passwordhash: passwordEncrypted,email: "[email protected]",}).then(function () {
                    return res.status(200).send(JSON.stringify({
                        error: false,message: "Successfully registered user!",}))
                }).catch(function (error) {
                    throw [true,error];
                });
            }
            else {
                firestore.collection("users").doc(username).set({
                    username: username,}));
                }).catch(function (error) {
                    throw [true,error];
                });
            }
        }
        catch (error) {
            throw [true,error];
        }
    }
    catch (error) {
        console.log(error);
        const [isError,errorMessage] = error;

        return res.status(404).send(JSON.stringify({
            error: isError,message: errorMessage,}));
    }
});

终端输出

(节点:29448)未处理的PromiseRejectionWarning:[对象数组] (节点:29448) UnhandledPromiseRejectionWarning:未处理的承诺拒绝。这个错误要么是因为在没有 catch 块的情况下抛出了异步函数,要么是因为拒绝了一个没有用 .catch() 处理过的承诺。要在未处理的承诺拒绝时终止节点进程,请使用 CLI 标志 --unhandled-rejections=strict(请参阅 https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode)。 (拒绝编号:1) (节点:29448)[DEP0018] 弃用警告:不推荐使用未处理的承诺拒绝。将来,未处理的承诺拒绝将以非零退出代码终止 Node.js 进程。

解决方法

您有多个并发承诺链,其中一些可能会独立失败。您需要将所有逻辑整合到一个承诺链中。

return firestore.collection("users").get(username)
  .then((data) => {
    if (data.empty == false) {
      throw [true,"Already registered user!"];
    }
  })
  .then(() => {
    if (username == '') {
      return firestore.collection("users").add({/* Your data */});
    }

    return firestore.collection("users").doc(username).set({/* Your data */});
  })
  .then(() => {
    return res.status(200);
  })
  .catch((err) => {
    return res.status(500);
  });

您也可以尝试使用 async/await,这将大大简化这样的逻辑。