I'm trying to loop through a /users path and join it to my auth().listUsers result however this code:
export async function getSomeUsers(amount: number) {
try {
const listUsersResult = await admin.auth().listUsers(amount)
const parsedUsers = listUsersResult.users.map(stripUserSensitiveInfo).map(async user => {
console.log("try read_______________" + user.uid)
let userProfileSnapshot = await admin
.database()
.ref("users/" + user.uid)
.once("value")
console.log("end try read_______________" + user.uid)
return { ...user, userProfileSnapshot }
})
return parsedUsers
} catch (error) {
console.error("Error listing users:", error)
throw new Error("Error users" + error)
}
}
gives this error
Converting circular structure to JSON at JSON.stringify () at stringify
but this code works fine
export async function getSomeUsers(amount: number) {
try {
const listUsersResult = await admin.auth().listUsers(amount)
const parsedUsers = listUsersResult.users.map(stripUserSensitiveInfo).map( user => {
return 1
})
return parsedUsers
} catch (error) {
console.error("Error listing users:", error)
throw new Error("Error users" + error)
}
}
The problem is within the embedded async calls in the map
operator In order to make it work, you would need to either wait for each iteration, which would also be VERY inefficient. This is because for every additional query the time taken increases Linearly. My proposal is to convert the entire logic in a way that is scalable. This is fortunately the case with your listAllUsers()
function that returns all the results on one call
export async function getSomeUsers(amount: number) {
try {
/**
* fetch all the users with the provided limit
*/
const allUsers = await admin.auth().listUsers(amount)
/**
* loop through the returned values and create a promise to fetch
* Each of their document
*/
const listUsersResult = allUsers.users.map(user => {
return admin
.database()
.ref("users/" + user.uid)
.once("value")
})
/**
* When all the user documents have been fetched, iterare through them and deduce their values
*/
const parsedUsers = await Promise.all(listUsersResult).then(docSnashots => {
return docSnashots.map(snapshot => {
console.log("end try read_______________" + snapshot.val())
/**
* The records need to be matched with the original values
*/
const originalUserData = allUsers.users.find(u => u.uid === snapshot.key)
return { ...originalUserData, ...snapshot.val() }
})
})
return parsedUsers
} catch (error) {
console.error("Error listing users:", error)
throw new Error("Error users" + error)
}
}
NOTE this method is more compute intensive because of the loops, but more time efficient since every read operation is independent of the other. It can be modified for situations where you're sure the read operations will always take a very short time and (Maybe) would be more resource efficient than the computation of the loops