简体   繁体   中英

Firestore return after promise

I'm using Firestore, Cloud Functions and Dialogflow to create a Google Home app. My cloud function should return a calculation based on values in a collection, but I can only return a Promise.

// query firestore based on user
var transactions = db.collection('accounts')
               .doc(request.body.result.parameters.accountowner)
               .collection('transactions');
var accountbalance = await transactions.get()
    .then(snapshot => {
        var workingbalance = 0
        snapshot.forEach(doc => {
            workingbalance = workingbalance + doc.data().amount;
        });
        return workingbalance
    })
    .catch(err => {
        console.log('Error getting transactions', err);
    });

console.log(accountbalance)
balanceresponse = {
    "speech": request.body.result.parameters.accountowner + " has a balance of $" + accountbalance,
    "displayText": request.body.result.parameters.accountowner + " has an account balance of $" + accountbalance,
    "data": {},
    "contextOut": [],
    "source": "system"
}

response.send(balanceresponse);    

How can I wait for the promise to return the actual value before calling response.send? I have also tried to put the response.send inside a then, but the function completes and sends headers before the operation completes.

If you're working with promises, you need to return values as part of the Promise.then chain. This is usually done by chaining a bunch of .then() calls/blocks together. Remember, the then() portion will only be called when a Promise resolves.

In your case, it looks like you can just generate balanceresponse and call the response.send() after you calculate workingbalance , inside the same block of code. The call to response.send() doesn't need to be at the end of the function. So you might have that block look something like:

.then(snapshot => {
    var workingbalance = 0
    snapshot.forEach(doc => {
        workingbalance = workingbalance + doc.data().amount;
    });

    balanceresponse = {
      "speech": request.body.result.parameters.accountowner + " has a balance of $" + workingbalance,
      "displayText": request.body.result.parameters.accountowner + " has an account balance of $" + workingbalance,
      "data": {},
      "contextOut": [],
      "source": "system"
    }

    response.send(balanceresponse); 
})

If, for some reason, you wanted to separate the calculation and compute the balanceresponse in a different block, you could do so. I don't necessarily recommend this, but it has some merits (for example, you could put multiple catch blocks after each part, which I've shown here):

// query firestore based on user
var transactions = db.collection('accounts')
               .doc(request.body.result.parameters.accountowner)
               .collection('transactions');
await transactions.get()

    .then(snapshot => {
        var workingbalance = 0
        snapshot.forEach(doc => {
            workingbalance = workingbalance + doc.data().amount;
        });
        return workingbalance
    })

    .catch(err => {
        console.log('Error getting transactions', err);
    });

    .then( accountbalance => {
        balanceresponse = {
            "speech": request.body.result.parameters.accountowner + " has a balance of $" + accountbalance,
            "displayText": request.body.result.parameters.accountowner + " has an account balance of $" + accountbalance,
            "data": {},
            "contextOut": [],
            "source": "system"
        }
        response.send(balanceresponse);    
    })

    .catch(err => {
        console.log('Error sending response', err);
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM