I really need to brush up on my async await and promises. I would love some advice.
I'm making an async function call to firebase firestore. The function should return a string depending on a single input param.
The feature is for a 1-1 user chat. The function is to create the chat/find existing chat, and return its ID.
Right now, I am getting undefined
as the return value of openChat
and can't work out why. The function otherwise works, apart from the return.
I have two functions. One is a React class ponent lifecycle method, the other my firebase async function.
Here is the class ponent lifecycle method:
async getChatId(userId) {
let chatPromise = new Promise((resolve, reject) => {
resolve(openChat(userId))
})
let chatId = await chatPromise
console.log('chatId', chatId) //UNDEFINED
return chatId
}
async requestChat(userId) {
let getAChat = new Promise((resolve, reject) => {
resolve(this.getChatId(userId))
})
let result = await getAChat
console.log('result', result) //UNDEFINED
}
render() {
return (<button onClick = {() => this.requestChat(userId)}>get id</button>)
}
and here is the async function:
// both my console.log calls show correctly in console
// indicating that the return value is correct (?)
export async function openChat(otherPersonId) {
const user = firebase.auth().currentUser
const userId = user.uid
firestore
.collection('users')
.doc(userId)
.get()
.then(doc => {
let chatsArr = doc.data().chats
let existsArr =
chatsArr &&
chatsArr.filter(chat => {
return chat.otherPersonId === otherPersonId
})
if (existsArr && existsArr.length >= 1) {
const theId = existsArr[0].chatId
//update the date, then return id
return firestore
.collection('chats')
.doc(theId)
.update({
date: Date.now(),
})
.then(() => {
console.log('existing chat returned', theId)
//we're done, we just need the chat id
return theId
})
} else {
//no chat, create one
//add new chat to chats collection
return firestore
.collection('chats')
.add({
userIds: {
[userId]: true,
[otherPersonId]: true
},
date: Date.now(),
})
.then(docRef => {
//add new chat to my user document
const chatInfoMine = {
chatId: docRef.id,
otherPersonId: otherPersonId,
}
//add chat info to my user doc
firestore
.collection('users')
.doc(userId)
.update({
chats: firebase.firestore.FieldValue.arrayUnion(chatInfoMine),
})
//add new chat to other chat user document
const chatInfoOther = {
chatId: docRef.id,
otherPersonId: userId,
}
firestore
.collection('users')
.doc(otherPersonId)
.update({
chats: firebase.firestore.FieldValue.arrayUnion(chatInfoOther),
})
console.log('final return new chat id', docRef.id)
return docRef.id
})
}
})
}
If you have any useful tips whatsoever, I would be forever grateful to hear them!
Expected results are a returned string. The string is correctly displayed the console.log of the async function).
Actual results are that the return value of the async function is undefined.
I really need to brush up on my async await and promises. I would love some advice.
I'm making an async function call to firebase firestore. The function should return a string depending on a single input param.
The feature is for a 1-1 user chat. The function is to create the chat/find existing chat, and return its ID.
Right now, I am getting undefined
as the return value of openChat
and can't work out why. The function otherwise works, apart from the return.
I have two functions. One is a React class ponent lifecycle method, the other my firebase async function.
Here is the class ponent lifecycle method:
async getChatId(userId) {
let chatPromise = new Promise((resolve, reject) => {
resolve(openChat(userId))
})
let chatId = await chatPromise
console.log('chatId', chatId) //UNDEFINED
return chatId
}
async requestChat(userId) {
let getAChat = new Promise((resolve, reject) => {
resolve(this.getChatId(userId))
})
let result = await getAChat
console.log('result', result) //UNDEFINED
}
render() {
return (<button onClick = {() => this.requestChat(userId)}>get id</button>)
}
and here is the async function:
// both my console.log calls show correctly in console
// indicating that the return value is correct (?)
export async function openChat(otherPersonId) {
const user = firebase.auth().currentUser
const userId = user.uid
firestore
.collection('users')
.doc(userId)
.get()
.then(doc => {
let chatsArr = doc.data().chats
let existsArr =
chatsArr &&
chatsArr.filter(chat => {
return chat.otherPersonId === otherPersonId
})
if (existsArr && existsArr.length >= 1) {
const theId = existsArr[0].chatId
//update the date, then return id
return firestore
.collection('chats')
.doc(theId)
.update({
date: Date.now(),
})
.then(() => {
console.log('existing chat returned', theId)
//we're done, we just need the chat id
return theId
})
} else {
//no chat, create one
//add new chat to chats collection
return firestore
.collection('chats')
.add({
userIds: {
[userId]: true,
[otherPersonId]: true
},
date: Date.now(),
})
.then(docRef => {
//add new chat to my user document
const chatInfoMine = {
chatId: docRef.id,
otherPersonId: otherPersonId,
}
//add chat info to my user doc
firestore
.collection('users')
.doc(userId)
.update({
chats: firebase.firestore.FieldValue.arrayUnion(chatInfoMine),
})
//add new chat to other chat user document
const chatInfoOther = {
chatId: docRef.id,
otherPersonId: userId,
}
firestore
.collection('users')
.doc(otherPersonId)
.update({
chats: firebase.firestore.FieldValue.arrayUnion(chatInfoOther),
})
console.log('final return new chat id', docRef.id)
return docRef.id
})
}
})
}
If you have any useful tips whatsoever, I would be forever grateful to hear them!
Expected results are a returned string. The string is correctly displayed the console.log of the async function).
Actual results are that the return value of the async function is undefined.
Share edited May 14, 2020 at 10:23 user11141611 asked Feb 12, 2019 at 16:16 Yesman500Yesman500 1561 gold badge2 silver badges8 bronze badges 2-
1
What about:
let chatId = await openChat(userId);
andlet result = await this.getChatId(userId)
? Also, you're returning nothing from theopenChat
function. – briosheje Commented Feb 12, 2019 at 16:21 - See Why is value undefined at .then() chained to Promise? – guest271314 Commented Feb 12, 2019 at 16:25
2 Answers
Reset to default 6You do not return anything from your openChat
function, so that function resolves to undefined
.
You have to write:
export async function openChat(otherPersonId) {
const user = firebase.auth().currentUser
const userId = user.uid
return firestore // here you need to return the returned promise of the promise chain
.collection('users')
.doc(userId)
.get()
/* .... */
}
And those new Promise
in getChatId
and requestChat
do not make much sense. It is sufficient to await the result of openChat(userId)
or this.getChatId(userId)
async getChatId(userId) {
let chatId = await openChat(userId)
console.log('chatId', chatId) //UNDEFINED
return chatId
}
async requestChat(userId) {
let result = await this.getChatId(userId)
console.log('result', result) //UNDEFINED
}
You should await
the results from your firestore calls if you want to return their values, you are already using async
functions :
export async function openChat(otherPersonId) {
const user = firebase.auth().currentUser
const userId = user.uid
const doc = await firestore
.collection('users')
.doc(userId)
.get()
let chatsArr = doc.data().chats
let existsArr =
chatsArr &&
chatsArr.filter(chat => chat.otherPersonId === otherPersonId)
if (existsArr && existsArr.length >= 1) {
const theId = existsArr[0].chatId
//update the date, then return id
await firestore
.collection('chats')
.doc(theId)
.update({
date: Date.now(),
})
return theId
} else {
const docRef = await firestore
.collection('chats')
.add({
userIds: { [userId]: true, [otherPersonId]: true },
date: Date.now(),
})
const chatInfoMine = {
chatId: docRef.id,
otherPersonId: otherPersonId,
}
//add chat info to my user doc
firestore
.collection('users')
.doc(userId)
.update({
chats: firebase.firestore.FieldValue.arrayUnion(chatInfoMine),
})
//add new chat to other chat user document
const chatInfoOther = {
chatId: docRef.id,
otherPersonId: userId,
}
firestore
.collection('users')
.doc(otherPersonId)
.update({
chats: firebase.firestore.FieldValue.arrayUnion(chatInfoOther),
})
console.log('final return new chat id', docRef.id)
return docRef.id
}
}
You should also directly await your calls to the function :
async getChatId(userId) {
let chatId = await openChat(userId)
console.log('chatId', chatId) //UNDEFINED
return chatId
}
async requestChat(userId) {
let result = await this.getChatId(userId)
console.log('result', result) //UNDEFINED
}