Firebase云功能问题-与承诺相关的

时间:2020-07-25 07:39:07

标签: javascript node.js firebase promise google-cloud-functions

我对可调用的Firebase云功能( exports.listAllUsers )有问题。

后端:Nodejs和Firebase-Cloud_functions使用 admin.auth()。listUsers
问题:结果(usersList;具有用户uid的数组)在cloud-functions-emulator(日志)中确定,但在客户端中不正确(浏览器中的console.log(usersList)为空)
也许是与...有关的问题:对诺言的理解不佳。第二个代码示例正在使用async / await,但未使用.then()。

函数 listAllUsers 的代码基本上是从文档复制并粘贴的(原始代码片段:https://firebase.google.com/docs/auth/admin/manage-users#list_all_users)。我的代码修改为5(代码中的注释),以获取用户uid的列表:

    exports.listAllUsers = functions.https.onCall(() => { // -1) callable function
      const usersList = ['12323211'] // ----------------------2) first user uid, just a sample
      function listAllUsers (nextPageToken) {
        // List batch of users, 1000 at a time.
        admin.auth().listUsers(1000, nextPageToken)
          .then((listUsersResult) => {
            listUsersResult.users.forEach((userRecord) => {
              usersList.push(userRecord.uid) // --------------3) get users uids
            })
            if (listUsersResult.pageToken) {
              // List next batch of users.
              listAllUsers(listUsersResult.pageToken)
            }
            console.log(usersList) //-------------------------4) list users uid (cloud functions console)
            return usersList //-------------------------------5) return to the client the same as showed at the console
          })
          .catch((error) => {
            console.log('Error listing users:', error)
            return null
          })
      }
      // Start listing users from the beginning, 1000 at a time.
      listAllUsers()
    })

客户端中的方法是...

getUsersList: async function (userType) {
      const usersList = await this.$fb.functions().httpsCallable('listAllUsers')()
      console.log('usersList: ', usersList)
    }

我正在使用Firebase模拟器。云功能日志正常,您可以看到示例uid和其他uid:

cloud function emulator console output

但是我在客户端没有得到相同的信息:

client console output

我认为我在做与诺言有关的错误...因为简化了代码,所以在异步/等待中工作

    exports.listAllUsers = functions.https.onCall(async () => {
      try {
        listUsersResult = await admin.auth().listUsers()
        return listUsersResult
      } catch (error) {
        console.log('Error listing users:', error)
        return null
      }
    })

Browser console output (reduced code with async/await)

但是在then()中却不起作用...

    exports.listAllUsers = functions.https.onCall(() => {
      admin.auth().listUsers()
        .then((listUsersResult) => {
          return listUsersResult
        })
        .catch((error) => {
          console.log('Error listing users:', error)
          return null
        })
    })

Browser console output (reduced code with .then())

我可以使用async / await重构代码的初始片段,但是我对使用原始代码(.then()风格的解决方案很感兴趣;我始终使用async / await,因为我在js上很新)。有人可以帮助我吗?谢谢!

2 个答案:

答案 0 :(得分:1)

这是因为在使用async/await版本的情况下,您通过执行操作正确返回了listUsersResult

    listUsersResult = await admin.auth().listUsers()
    return listUsersResult

但是,对于then版本,您不需要。您应该返回整个promise链,如下所示:

exports.listAllUsers = functions.https.onCall(() => {
  return admin.auth().listUsers()   // !!! Note the return here  !!!
    .then((listUsersResult) => {
      return listUsersResult
    })
    .catch((error) => {
      console.log('Error listing users:', error)
      return null
    })
})

答案 1 :(得分:1)

最后,我决定为我的云功能编写一个async/await版本。第一个代码片段中的then版本不仅需要在整个Promise链中添加return(它最初是因为递归性而抱怨,也许是要求我将async添加到整个Promise链中)。包装函数listAllUsers ...我希望then版本仅从firebase文档中复制并粘贴,但它需要更多内容。

我想将此自制版本(但经过初步测试)共享为具有异步/等待且无递归的示例,以列出具有admin.auth().listUsers(maxResults?, pageToken?)的用户:

// get list of users
exports.listAllUsers = functions.https.onCall(async () => {
  const usersList = []
  try {
    let listUsersResult
    let nextPageToken
    do {
      if (listUsersResult) {
        nextPageToken = listUsersResult.pageToken
      }
      // eslint-disable-next-line no-await-in-loop
      listUsersResult = await admin.auth().listUsers(1000, nextPageToken)
      listUsersResult.users.forEach((userRecord) => {
        usersList.push(userRecord.uid)
      })
    } while (listUsersResult.pageToken)
    return usersList
  } catch (error) {
    console.log('Error listing users:', error)
    return null
  }
})