How to handle async API calls in Actions on Google - actions-on-google

I'm using actions-on-google github nodejs app with DialogFlow. I'm trying to figure out how to make an async api call that takes longer than 5 seconds and return the response to the user when the response is ready, considering that actions on google returns Malformat error if a response is not received from the intent within 5 seconds.
This is a simple code snippet of my code:
app.intent('first-intent', async (conv: any) => {
conv.ask('Please wait while we make our long api call...');
await myPrivateFunction();
})
// I have put API_RESPONSE_RECEIVED as Events in DialogFlow
app.intent('second-intent', (conv: any) => {
console.log('This is second-intent');
var response = conv.data.apiResponse;
conv.ask(response);
})
function myPrivateFunction(): Promise<void> {
utils.apiCall().then(apiResponse => {
console.log('api response received');
conv.data.apiResponse = apiResponse;
conv.followup('API_RESPONSE_RECEIVED');
});
}
In my Firebase logs I can see "Please wait while we make our long api call..." and "api response received", but not "This is second-intent". If I put conv.followup('API_RESPONSE_RECEIVED') outside the api call right after conv.ask('Please wait while we make our long api call...'), I see "This is second-intent". So, app.followup looks OK and apparently the problem is about how I'm handling the promise, but I don't know how to fix it.
I'm using TypeScript targeting es5 in my development environment. So, I can use await/async on my api call. However, using await causes that malformat error since the api call takes longer than 5 seconds.

We don't really have a good way to handle this right now, but we have a couple of approaches that sorta work based on your needs.
Notifications are currently available for the Assistant on smartphones, and they're coming for speakers. In some cases, it might make sense to say that you're working on the problem and you'll send a notification when you have it, and then resume the conversation from the notification.
Another approach is to use the Media Response to play a bit of "hold music". Under this scheme, you would start the async call, but also immediately send back the "hold music response". When the long async call completes, it would save the result in a local cache. At the end of the segment of music, your webhook will get a notice that the music has completed. If you have the result available in the local cache, you can report it at that time, otherwise you would play more hold music and repeat this process.

Related

How to get a Cloud Functions Callback URL to use during an API callback after it completes a money transaction, Flutter App

I need a callback URL so that when a mobile money API completes a payment transaction, my app can receive a message about the transaction status. I'm building a flutter app. I have seen that cloud functions may be the answer. So, I need help on how to get started on creating this callback URL.
I'm yet to try anything because all the material I have seen talks about JavaScript and websites. I need material on doing this in the flutter mobile app.
look at this snippet I hope it helps
// await for your first function t
await moneyFuntion()
.whenComplete(() async => await anotherAPIFuntion())
.onError((error, stackTrace) {
log("$error");

Wait for specific key-value pair to change in HTTP response?

I'm building a mobile application with Flutter and using Firebase(firestore) to store data. When a user creates an account, I need to make POST request to an external website using that websites api, which will then return me a response that tells me if the user info is still registering (i.e. either provisioning or operational). Once it is operational, I will then get that data and store it in the users account information on firestore. However, it may take some up to 10 minutes for that information to be in the operational status. Can I use "retry" to repeatedly fetch this resource and check if the status has changed?
You can try using Timer to make that request periodically and check for status.
import 'dart:async';
main() {
const timeout = const Duration(seconds: 10);
new Timer.periodic(timeout, (Timer t) {...});
// Run your API request and logic here ^
}
If the response is as expected, just cancel the Timer and proceed with your application flow.

Async and Parallel Processing

There have been more than a few posts on this, but I still can't get my head wrapped around this particular problem.
If I have to call three external sites, Facebook, Twitter, and Instagram, and I launch all three with async parallel, and it hangs up for 20 seconds waiting for Facebook to respond, I'm unsure what happens. Does the call the Twitter start, and Instagram, and they both run and possibly complete before the call to Facebook, or does that entire user thread pause until the next round of the event loop, and another users call go through? It looks like the latter to us. Or does the entire thread grind to a halt and wait?
Per the request, here is a cut down version of the code. Service_requests is an array of functions that call Facebook, Instagram, and Twitter. There was a bunch of other stuff going on in here as well, but the meat of it is pretty simple.
Async.parallel(service_requests, function (err, results)
{
if (err) { next(err); return; }
var articles = [];
for (var i = 0; i < results.length; i++)
{
articles = articles.concat(results[i]);
}
next(null, articles);
});
When you make parallel requests to services they all happen 'at the same time'. So if facebook took 20 seconds to return, twitter took 15 seconds and instagram took 25 seconds, you will have all of your data in 25 seconds from when you initiate all of your requests.
moreover, when node waits for responses from these services it its free to service other requests.
the event loop does not grind to a halt and wait for the responses, it continues to do other work if other work exists.
when all 3 services respond with data the async lib will call your final callback with the results.

If FB.init({status:true}) causes the Javascript SDK to load status, how can I get the status?

If FB.init({status:true}) causes the Javascript SDK to load status, what is the most efficient way I can get the status?
Do I have to use the async call to FB.getLoginStatus()? Or is there a synchronous way to get the status that would save a web request?
If you want to do it using JavaScript, then the only way is to make FB.getLoginStatus() call. However, if you are worried about, say, slow response time, then you could simply save the status in a cookie once a successful authorization process is completed.
Though, since we are talking about milliseconds, I would discourage you from going that way.
The most efficient way to retrieve the status is subscribing to the auth.authRepsonseChange event.
example:
var auth_response_change_callback = function(response) {
console.log("auth_response_change_callback");
console.log(response);
};
FB.Event.subscribe('auth.authResponseChange', auth_response_change_callback);
Source: FB event documentation

Is it possible to do non-blocking Facebook API calls, using node.js?

I want to use node.js to boost my Facebook applications performance. Imagine application that tries to compute who is you best friend on Facebook, fetching a lot of data from API calls - determining how many times your friends have posted to your wall, how many photos you have marked on together - so on.
So instead of running that calls one after one, as I do using PHP I have an idea to send them all together to Facebook using non-blocking, asynchronous nature of Node.js.
So overall execution time will be the time of most time consuming API call, but not the sum of execution time of the every call, right?
I try to use node-facebook-sdk (https://github.com/tenorviol/node-facebook-sdk) to make Facebook API calls and it seems to be that it's blocking, isn't it?
Just quick and dirty modification of example code, requesting 3 user profiles, seems that calls are not asynchronous, each sending to Facebook after previous has completed. Are there any way to avoid that?
Thank in advance!
var fbsdk = require('facebook-sdk');
var facebook = new fbsdk.Facebook({
appId : '_APPID_',
secret : '_SECRET_'
});
var i = 0;
setInterval(function() {
i++;
console.log("TICK " + i);
}, 500);
facebook.api('/100000997949108', function(data) {
console.log(data);
});
facebook.api('/1609464095', function(data) {
console.log(data);
});
facebook.api('/100000560820400', function(data) {
console.log(data);
});
This library will help you out with all things async. I hashed the particular method you would want to use for your problem, but the library as a whole is excellent at abstracting some of the more tedious (and ugly!) async patterns away. Great transitioning tool for those coming from procedural and you can take a peak under the covers if you want to learn some async patterns.
https://github.com/caolan/async/#parallel