2

I need to retrieve information from a Firestore Document when another document is created. When I try to do this I get hit with an error about the function not being async. It has been so long since I used javascript I am basically a novice again and have no idea how to fix this.

ok, so I am using Firebase Cloud Functions and the function in question is a Firestore .onCreate() trigger.

When the function is triggered I set a sender variable (which is the document ID from a different collection that I need to retrieve)

then I try to get the document as per the documentation.

The function ends up like this:

exports.pushFriendRequestNotification = functions.firestore.document('friends/{friendID}')
.onCreate((snap, context) => {
  // when friend request is created
  
  data = doc.data()//get request data
  sender = data["sender"]//get request sender from data
  
const requestRef = db.collection('User').doc(sender);
const doc = await requestRef.get();//get user data of sender
if (!doc.exists) {
    console.log('No such document!');
} else {
    console.log('Document data:', doc.data());
    
            
}
});

when I run this in the emulator I get this error:

const doc = await requestRef.get();//get user data of sender
            ^^^^^

SyntaxError: await is only valid in async functions and the top level bodies of modules

I have absolutely no idea where to go from here.

Can anyone help me with this? Thanks

3 Answers 3

2

The await keyword is valid only in an async function.

exports.pushFriendRequestNotification = functions.firestore.document('friends/{friendID}')
  .onCreate(async (snap, context) => {
        //  ^^^^^
  })

If you are (or need to) use synchronous function then you would have to use promise chaining.

exports.pushFriendRequestNotification = functions.firestore.document('friends/{friendID}')
  .onCreate((snap, context) => {
     return requestRef.get().then((snapshot) => {
       if (snapshot.exists) { ... }
     })
  })

Apart from that, the order of variables/statements looks incorrect. With the current code (as in original question), you may end up getting an error: "Cannot access 'doc' before initialization" Try refactoring it like this:

exports.pushFriendRequestNotification = functions.firestore.document('friends/{friendID}')
  .onCreate(async (snap, context) => {
    // accessing data from newly created doc
    const newDocData = snap.data()

    // const sender = "" // ??
     
    const requestRef = db.collection('User').doc(sender);  
    const doc = await requestRef.get();//get user data of sender
    if (!doc.exists) {
      console.log('No such document!');
    } else {
      console.log('Document data:', doc.data());      
    }
  })

Where is the sender coming from? I've just commented it above but if the sender is present in new document then you can access it by: const sender = newDocData.sender

Sign up to request clarification or add additional context in comments.

2 Comments

while every answer here gave basically the same answer, I've chosen to mark your as correct because you spotted the doc.data() mistake (thanks).... also sender was indeed present in the new document, I couldn't find the documentation on accessing specific fields in a document (it was 2AM, I was VERY tired hah).... I figured it was between .sender and ["sender"] but you beat me to it :P ..... cheers :)
@Andy glad to hear that :D Checkout this Firecast for better understanding of Firestore triggers. Also .sender and ["sender"] are same thing (Property Accessor). Your 'doc' would have been undefined.
2

If your using await you have to specify that function is asynchronous. Otherwise it will throw error.

exports.pushFriendRequestNotification = functions.firestore.document('friends/{friendID}').onCreate(async (snap, context) => {
    // when friend request is created
    data = doc.data()//get request data
    sender = data["sender"]//get request sender from data
    const requestRef = db.collection('User').doc(sender);
    const doc = await requestRef.get();//get user data of sender
    if (!doc.exists) {
        console.log('No such document!');
    } else {
        console.log('Document data:', doc.data());      
    }
});

Yet some of your references is unknown to us. Maybe this code is not completed.

The main point is you need to understand when you can access async/await or Promise

Comments

1

All await methods must be inside an async block or be handled in an async manor using .then() promises

in this case, the parent function is on this line .onCreate((snap, context) => {

simply inserting an async at the start of the variables will upgrade the arrow function to an async arrow function .onCreate(async (snap, context) => {

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.