0

I am using Firebase Functions. Basically, an API corresponds to one function. So, I must return the result within the function. See the pseudocode below.

export const someAPI = functions.https.onRequest((...) =>{
     parameter = get the parameter from the request
     data = searchDatabase(parameter)

     if data is not null
          do something and create a result
     else
          do something else and create a different result

     send the result as response.
});

I have created the searchDatabase function, and it works. The problem is, the query result is retrieved by a callback.

function searchDatabase(token:string):string
{
    const db = admin.database().ref("mydata");
    db.....once("value",
        function(snapshot){
            snapshot.forEach(
                function(data)
                {
                    const deviceId = data.val().id;
                    return false;
                }
            );
         }
    )

    return ?; <- I need to return `deviceId` at this point.
}

I have read this answer, and I would like to take "the blue pill", but that answer was for Java and it seems that there is no semaphore for TypeScript. Can I do the similar thing in TypeScript?


After reading the comment, I decided to use async/wait. I do not know how to make the API function itself an async function, so I did this.

export const someAPI = functions.https.onRequest((request, response) =>{
  realFunction(request, response);
});

async function realFunction(request: express.Request, response: express.Response)
{
     parameter = get the parameter from the request
     data = await searchDatabase(parameter)

     if data is not null
          do something and create a result
     else
          do something else and create a different result

     send the result as response.
 }

and I made the searchDatabase function return a Promise.

async function searchDatabase(token:string): Promise<string>
{
    return new Promise<string>((resolve, reject) => {
        const db = admin.database().ref("mydata");
        db.orderByChild("..").equalTo(token).once("value")
            .then(function(snapshot){
                snapshot.forEach(
                    function(data)
                    {
                        //match found, but what about all other cases?
                        const deviceId = data.val().id;
                        resolve(deviceId); 
                        return false;
                    }
                );
                resolve(null);
             })
             .catch(reason=>{resolve(null);})
    });
}
Damn Vegetables
  • 11,484
  • 13
  • 80
  • 135
  • You need to use promises for async programming when working with JavaScript (and TypeScript). You really have no other option. There is lots of discussion about this in the Cloud Functions for Firebase documentation, and the sample code provided. – Doug Stevenson Jun 29 '18 at 23:16
  • In TypeScript, also, you have async/await syntax, which can ease some of the hassle of working with promises, but you still have to essentially understand how they work. – Doug Stevenson Jun 29 '18 at 23:18
  • I decided to use async/await. It works when there is a match and I set the `resolve`. The problem is when there is no match in the database. How to set the `resolve` to null in all other cases? Please see the appended code in the OP. "the sample code provided" Where is the sample code that reads database in the API function? I cannot find one. – Damn Vegetables Jun 30 '18 at 03:48
  • I think I got it working by replacing the arguments of `once` to `then` and adding `catch` (after all, `once` was a Promise). – Damn Vegetables Jun 30 '18 at 04:54

0 Answers0