firebase 云函数调用回调

firebase cloud functions invoke callback

我正在使用 firebase admin SDK 为我的网络应用程序创建新用户。

// function to create user and store additional info in firestore
exports.createUser = functions
    .https.onCall((data, context) => {
      admin.auth().createUser({
        phoneNumber: data.phoneNumber,
        displayName: data.displayName,
      }).then((user) => {
        // store data in firestore
        admin.firestore().collection("user").doc(user.uid).set({...data});
      }).catch((err) => {
        // handle error
      });
    });

当我从客户端调用该函数(将其附加到 onClick 事件)时,我想等到用户成功添加到 firestore 并调用 fetchUser 函数,这样我就可以看到包含新添加用户的新数据列表.当前调用 fetchUser 并刷新页面,但我在刷新之前看不到新添加的用户。

const createUser = functions.httpsCallable('createUser');

const createNewUser = () => {
    createUser({
      phoneNumber: "+1111111111111",
      displayName: "test",
      introduction: "testcreate",
    })
  .then((res) => {
    fetchUser(); // fetchUser just fetches user data from firestore and rerenders page 
  })
  .catch((err) => {
    console.log(err);
  });

};

总而言之,我可以知道云函数何时会完成它的工作和运行一个特定的函数或任务吗?

看起来您没有正确地 return 承诺,因此函数在文档更新之前终止。请尝试添加 return 语句,如下所示。

exports.createUser = functions
    .https.onCall((data, context) => {
      return admin.auth().createUser({
        phoneNumber: data.phoneNumber,
        displayName: data.displayName,
      }).then(async (user) => {
        // store data in firestore
        await admin.firestore().collection("user").doc(user.uid).set({...data});
        return {data: user.uid}
      }).catch((err) => {
        // handle error
        return {error: error}
      });
    });

那么理想情况下,您应该在所有承诺都已解决(即更新文档)后收到响应。还要确保您没有启用 Firestore 本地缓存。

正如您将在 official Firebase video series 中有关“JavaScript Promises”的三个视频中看到的那样,您必须 return 触发背景中的 Promise 或值,Pub/Sub 或 Callable Cloud Function 当所有异步操作完成时。

这有两个关联的效果:

  1. 当异步操作完成时,它向 Cloud Functions 平台表明它可以终止并清理您的函数。
  2. 相反,直到异步操作完成,它指示Cloud Function平台在终止Cloud Function之前应该等待。

到 return 一个 Promise,因为您链接了几个异步 Firebase Admin SDK 方法(return Promise),您需要 return Promise chain 如下:

exports.createUser = functions.https.onCall((data, context) => {
    return admin  // <== See return here
    .auth()
    .createUser({
      phoneNumber: data.phoneNumber,
      displayName: data.displayName,
    })
    .then((user) => {
      // store data in firestore
        return admin   // <== See return here
        .firestore()
        .collection('user')
        .doc(user.uid)
        .set({ ...data }); 
    })
    .then(() => {
      // The set() method returns Promise<void>
      // To send data back to the client, return data that can be JSON encoded
      return { result: 'user created' };
    })
    .catch(error => {
      // See https://firebase.google.com/docs/functions/callable#handle_errors
      // on how to handle errors
    });
});

这样,当您的前端返回 Callable Cloud Function 响应时,您可以确定用户和 Firestore 文档已创建。


如果要使用async/await关键字,请按如下操作。请注意,不建议将 then()async/await.

混淆
exports.createUser = functions
    .https.onCall(async (data, context) => {   // <== See async here

        try {
            const user = await admin.auth().createUser({
                phoneNumber: data.phoneNumber,
                displayName: data.displayName,
            });

            await admin.firestore().collection("user").doc(user.uid).set({ ...data });
            return { result: 'user created' }
            
        } catch (error) {
            console.log(error);  // If desired
            // See https://firebase.google.com/docs/functions/callable#handle_errors
            // on how to handle errors
        }

    });

看看代码的可读性如何,就好像它是同步代码一样。