【问题标题】:Firebase Cloud Functions - Issues with PromisesFirebase 云函数 - Promise 问题
【发布时间】:2021-06-21 01:40:54
【问题描述】:

在运行我的 Firebase Cloud Function orgNew 时,我的承诺和代码执行顺序似乎无法正常工作。

控制台日志(缩短):

1: Function execution started
2: function checkLicenseKey() was successful
3: function checkPermissionsFromAuth() was successful 
4: result undefined
5: Error: TypeError: Cannot read property 'uid' of undefined // Points to marked spot in code 
6: Unhandled error Error: Unknown error code: failed to connect.
7: Function execution took 4663 ms, finished with status code: 500 
8: function getUserAuthObject() was successful { userObj is logged here }

我的 Firebase 云函数和一些额外的代码(缩短):

exports.orgNew = functions
  .region("europe-west3")
  .https.onCall((data, context) => {

      var userObj;
      var orgID;
      return (
        checkLicenseKey(data.licenseKey)
          .then((result) => {
            if (!result.isValid) {
              throw new functions.https.HttpsError(
                "permission-denied",
                "Invalid license key used"
              );
            }
            return checkPermissionsFromAuth(context);
          })
          .then((result) => {
            return getUserAuthObject(context.auth.uid);
          })
          .then((result) => {
            console.info(result); // Error: result is undefined (line 4 in console)!
            userObj = result; // Therefore userObj is also undefined!
            return createOrganization(data, userObj);
 //  It seems that this gets executed even when if my userObj isn't ready yet!
          })
          .then((result) => {
            orgID = result.id;
            return loadDataFromTemplate(orgID, context);
          })
          .then((result) => {
            return addMember(orgID, userObj);
          })
          .then((result) => {
            return sendConfirmation(userObj.email, userObj.displayName);
          })
          .then((result) => {
            return { orgID, success: true };
          })
          .catch((err) => {
            // handle error
            functions.logger.error("Error:", err);
            throw new functions.https.HttpsError("failed to connect");
          })
      );
  });

function createOrganization(data, userObj) {
    const organisationRef = admin.firestore().collection("org");
    const document = {
      title: data.title,
      description: data.description,
      meta: {
        id: organisationRef.id,
        creator: {
// Error points to the following line, obviously this is because userObj is still undefined.
          creatorUID: userObj.uid,
          creatorEmail: userObj.email,
          creatorName: userObj.displayName,
        },
        createdAt: admin.firestore.FieldValue.serverTimestamp(),
      },
      },
    };
    return organisationRef
      .add(document)
      .then((organisationRef) => {
        functions.logger.info("function createOrganization() was successful");
        return organisationRef;
      })
      .catch((error) => {
        functions.logger.error("Error creating organization: ", error);
        throw new functions.https.HttpsError("failed to connect", error);
      });
  }
  
  function getUserAuthObject(uid) {
    admin
      .auth()
      .getUser(uid)
      .then((userRecord) => {
        const obj = {
          uid: userRecord.uid,
          email: userRecord.email,
          displayName: userRecord.displayName,
        };
        return obj;
      })
      .then((result) => {
        functions.logger.info("function getUserAuthObject() was successful", result);
        return result
      })
      .catch((err) => {
        functions.logger.error("Error fetching user data:", err);
        throw new functions.https.HttpsError("failed to connect");
      });
  }

这里不包括所有其他功能,因为它们与问题无关。

非常感谢任何帮助。谢谢!

【问题讨论】:

  • 不相关说明:您还可以使用Promise.all 并行执行loadDataFromTemplateaddMembersendConfirmation 调用,因为它们似乎并不相互依赖。
  • @samthecodingman 很棒的建议,我会试试的。谢谢!

标签: javascript firebase promise google-cloud-functions


【解决方案1】:

从阅读代码(即未经测试)看来,这是因为您没有在 getUserAuthObject() 函数中返回 Promises chain。因此userObj 是未定义的。

你应该如下调整它:

  function getUserAuthObject(uid) {
    return admin  // !!! See the return here !!!
      .auth()
      .getUser(uid)
      .then((userRecord) => {
        const obj = {
          uid: userRecord.uid,
          email: userRecord.email,
          displayName: userRecord.displayName,
        };
        functions.logger.info("function getUserAuthObject() was successful", obj);
        return obj;
      })
      .catch((err) => {
        functions.logger.error("Error fetching user data:", err);
        throw new functions.https.HttpsError("failed to connect");
      });
  }

顺便说一句,看看我们如何简化这个函数中的 Promises 链,因为你不需要这样做

    return obj;
  })
  .then((result) => {
    functions.logger.info("function getUserAuthObject() was successful", result);
    return result
  })

因为 obj 不返回 Promise。这没有错,因为then() 返回了一个 Promise 但它是多余的。

【讨论】:

  • 谢谢!就是这样!很简单,但我错过了。是的,我对多余的部分有点不满意。也会解决这个问题。
猜你喜欢
  • 2019-05-16
  • 2019-10-26
  • 2020-03-31
  • 2017-08-10
  • 2021-05-31
  • 2018-01-21
  • 2020-05-16
  • 2020-07-27
  • 2017-09-14
相关资源
最近更新 更多