Mig82
Mig82

Reputation: 5478

How to use async fulfillment for Actions on Google

I'm trying to create a very simple voice app to query exchange rates by using Google Conversational Actions.

I use slots to get the to and from currencies. Then I try to call a web hook that in turn calls an API to get the rate between the two currencies.

First I tried defining the fulfillment function as async with await request, and then I tried return await request, but couldn't make the fulfillment function wait for the GET request to get back. Then I tried the code below using a Promise and now it times out. Not sure how to fix this.

const { conversation } = require('@assistant/conversation');
const functions = require('firebase-functions');
const request = require('request');

const app = conversation();

app.handle('get_exchange_rate', conv => {

    conv.session.params.rate = 0;

    let fromCcy = "EUR" //conv.session.params.currency_from_slot;
    let toCcy = "GBP" //conv.session.params.currency_to_slot;
    let url = `https://api.exchangeratesapi.io/latest?base=${fromCcy}&symbols=${toCcy}`;

    let options = {
        json: true
    };

    return new Promise((resolve, reject) => {
        request(url, options, (error, res, body) => {
            if (error) {
                console.log(error);
                reject(error);
            } else if (res.statusCode == 200) {
                console.log(body);
                conv.session.params.rate = body.rates[toCcy];
                resolve();
            }
        });
    });
});

exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

Note: All the samples I've found so far in the docs are for trivial sync work, like returning a static message. I've not been able to find any examples on how to make this work with async work such as this.

Update: I'm doing this from the Google Conversational Actions console found at Actions Console>Webhooks and using the Inline Cloud Functions fulfillment type.

enter image description here

enter image description here

The timeout problem somehow went away —literally over night— and I was suddenly able to address the response in my conversation prompts as $session.params.rate.

It seems like there's something off with the propagation of changes from the Google Actions Console to Firebase. I also notice that switching from the Develo tab to the Test one takes an awful lot of time to load. There's this message Your preview is being updated... with a spinner that sometimes just takes forever. Sometimes it just kind of times out and asks me for the version I want to preview again. Then I try it a second time and it's instantly done. Not a very good DX yet.

Upvotes: 1

Views: 494

Answers (1)

Scott M
Scott M

Reputation: 11

I was hitting very similar issues to you using async/await.

I commented out all the async stuff, and gradually brought it all back in one at a time, and eventually it started working... shrug

I'm using node-fetch in my handler

const fetch = require('node-fetch');
/* plus your other regular includes */

app.handle('checkCurrentPrice', async conv => {

    const url = 'https://api....';

    let body = {"key" : "var"};
  
    const externalRes = await fetch(url, {
        method: 'POST',
        body: JSON.stringify(body),
        headers: {"Content-Type" : "application/json"},
    });
  
    const json = await externalRes.json();
});

exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

Upvotes: 1

Related Questions