如何在 Actions on Google intent fulfillment V2 中调用 2 个或更多异步方法
How do I call 2 or more asynchronous methods in Actions on Google intent fulfilment V2
我在V1 DialogflowApp中成功调用了这2个方法(geocoder.reverse,timezone.data),但我现在升级到V2,似乎无法获得两个异步方法调用都正确。请帮忙。我分别使用这些包
- node-geocoder: ^3.22.0
node-google-timezone: ^0.1.1
const options = { provider: 'google', httpAdapter: 'https', apiKey: googleApi, formatter: 'json'};
const geocoder = NodeGeocoder(options);
const timezone = require('node-google-timezone');
app.intent('saving_prompt', (conv) => {
if (conv.data.area) {
const deviceCoordinatesStart = conv.device.location.coordinates;
const latitudeValueStart = deviceCoordinatesStart.latitude;
const longitudeValueStart = deviceCoordinatesStart.longitude;
let start = moment(); //Start time in UTC, you could also use dateTime()
let startTz = momentTz(); //used because of getting the Timezone
const timestamp = 1402629305; // Just a dud placeholder to fulfil timezone function
//GEOLOCATION REVERSAL (METHOD 1)
geocoder.reverse({lat:latitudeValueStart, lon:longitudeValueStart}, (err, res) => {
if (err) {
console.log(err);
}
let startLocation = res[0].administrativeLevels.level1long;
conv.data.startLocation = startLocation;
//GETTING LOCAL TIMEZONE FROM LAT/LONG AND TIMESTAMP (METHOD 2)
timezone.data(latitudeValueStart, longitudeValueStart, timestamp, (err, tz) => {
if (err) {
console.log(err);
}
var zoneHolder = tz.raw_response.timeZoneId;
const localTime = startTz.tz(zoneHolder).format('LLL');
conv.data.localTime = localTime;
app.ask('Your race starts by ' + localTime + 'at' + startLocation);
conv.ask(new Suggestions('End Race'));
});
});
} else { //Returned if permission not granted
conv.ask('You do not have your location on. Say "Locate me", to retrieve your location');
conv.ask(new Suggestions(['Locate me', 'Exit']));
}
});
//创建函数以在没有 'node-google-timezone' 包的情况下获取时区
function callTimezoneApi(lat, lon) {
return new Promise((resolve, reject) => {
let path = '/maps/api/timezone/json?location=' + lat +
',' + lon + '×tamp=' + ts + '&key=' + googleApi;
console.log('API Request: ' + host + path);
// Make the HTTP request to get the weather
http.get({
host: host,
path: path
}, (res) => {
let body = ''; // var to store the response chunks
res.on('data', (d) => {
body += d;
}); // store each response chunk
res.on('end', () => {
let response = JSON.parse(body);
let zoneHolder = response.timeZoneId;
let startTz = momentTz(); //used in fulfilling the Timezone
const localTime = startTz.tz(zoneHolder).format('LLL');
console.log(localTime);
return resolve(localTime);
});
res.on('error', (error) => {reject(error);});
});
});
}
如果您使用 Node 8,则可以使用 async/await 来解开嵌套的回调结构。它将确保您的异步调用在继续下一个依赖于另一个异步值的调用之前完成。
app.intent('saving_prompt', async (conv) => {
if (conv.data.area) {
const deviceCoordinatesStart = conv.device.location.coordinates;
const latitudeValueStart = deviceCoordinatesStart.latitude;
const longitudeValueStart = deviceCoordinatesStart.longitude;
let start = moment(); //Start time in UTC, you could also use dateTime()
let startTz = momentTz(); //used because of getting the Timezone
const timestamp = 1402629305; // Just a dud placeholder to fulfil timezone function
const startLocation = await new Promise((resolve, reject) => {
geocoder.reverse({ lat: latitudeValueStart, lon: longitudeValueStart }, (err, res) => {
if (err) {
console.log(err);
reject(err);
} else {
resolve(res[0].administrativeLevels.level1long);
}
});
});
const localTime = await new Promise((resolve, reject) => {
timezone.data(latitudeValueStart, longitudeValueStart, timestamp, (err, tz) => {
if (err) {
console.log(err);
reject(err);
} else {
var zoneHolder = tz.raw_response.timeZoneId;
resolve(startTz.tz(zoneHolder).format('LLL'));
}
});
});
app.ask('Your race starts by ' + localTime + 'at' + startLocation);
conv.ask(new Suggestions('End Race'));
} else { //Returned if permission not granted
conv.ask('You do not have your location on. Say "Locate me", to retrieve your location');
conv.ask(new Suggestions(['Locate me', 'Exit']));
}
});
我在V1 DialogflowApp中成功调用了这2个方法(geocoder.reverse,timezone.data),但我现在升级到V2,似乎无法获得两个异步方法调用都正确。请帮忙。我分别使用这些包
- node-geocoder: ^3.22.0
node-google-timezone: ^0.1.1
const options = { provider: 'google', httpAdapter: 'https', apiKey: googleApi, formatter: 'json'}; const geocoder = NodeGeocoder(options); const timezone = require('node-google-timezone'); app.intent('saving_prompt', (conv) => { if (conv.data.area) { const deviceCoordinatesStart = conv.device.location.coordinates; const latitudeValueStart = deviceCoordinatesStart.latitude; const longitudeValueStart = deviceCoordinatesStart.longitude; let start = moment(); //Start time in UTC, you could also use dateTime() let startTz = momentTz(); //used because of getting the Timezone const timestamp = 1402629305; // Just a dud placeholder to fulfil timezone function //GEOLOCATION REVERSAL (METHOD 1) geocoder.reverse({lat:latitudeValueStart, lon:longitudeValueStart}, (err, res) => { if (err) { console.log(err); } let startLocation = res[0].administrativeLevels.level1long; conv.data.startLocation = startLocation; //GETTING LOCAL TIMEZONE FROM LAT/LONG AND TIMESTAMP (METHOD 2) timezone.data(latitudeValueStart, longitudeValueStart, timestamp, (err, tz) => { if (err) { console.log(err); } var zoneHolder = tz.raw_response.timeZoneId; const localTime = startTz.tz(zoneHolder).format('LLL'); conv.data.localTime = localTime; app.ask('Your race starts by ' + localTime + 'at' + startLocation); conv.ask(new Suggestions('End Race')); }); }); } else { //Returned if permission not granted conv.ask('You do not have your location on. Say "Locate me", to retrieve your location'); conv.ask(new Suggestions(['Locate me', 'Exit'])); } });
//创建函数以在没有 'node-google-timezone' 包的情况下获取时区
function callTimezoneApi(lat, lon) {
return new Promise((resolve, reject) => {
let path = '/maps/api/timezone/json?location=' + lat +
',' + lon + '×tamp=' + ts + '&key=' + googleApi;
console.log('API Request: ' + host + path);
// Make the HTTP request to get the weather
http.get({
host: host,
path: path
}, (res) => {
let body = ''; // var to store the response chunks
res.on('data', (d) => {
body += d;
}); // store each response chunk
res.on('end', () => {
let response = JSON.parse(body);
let zoneHolder = response.timeZoneId;
let startTz = momentTz(); //used in fulfilling the Timezone
const localTime = startTz.tz(zoneHolder).format('LLL');
console.log(localTime);
return resolve(localTime);
});
res.on('error', (error) => {reject(error);});
});
});
}
如果您使用 Node 8,则可以使用 async/await 来解开嵌套的回调结构。它将确保您的异步调用在继续下一个依赖于另一个异步值的调用之前完成。
app.intent('saving_prompt', async (conv) => {
if (conv.data.area) {
const deviceCoordinatesStart = conv.device.location.coordinates;
const latitudeValueStart = deviceCoordinatesStart.latitude;
const longitudeValueStart = deviceCoordinatesStart.longitude;
let start = moment(); //Start time in UTC, you could also use dateTime()
let startTz = momentTz(); //used because of getting the Timezone
const timestamp = 1402629305; // Just a dud placeholder to fulfil timezone function
const startLocation = await new Promise((resolve, reject) => {
geocoder.reverse({ lat: latitudeValueStart, lon: longitudeValueStart }, (err, res) => {
if (err) {
console.log(err);
reject(err);
} else {
resolve(res[0].administrativeLevels.level1long);
}
});
});
const localTime = await new Promise((resolve, reject) => {
timezone.data(latitudeValueStart, longitudeValueStart, timestamp, (err, tz) => {
if (err) {
console.log(err);
reject(err);
} else {
var zoneHolder = tz.raw_response.timeZoneId;
resolve(startTz.tz(zoneHolder).format('LLL'));
}
});
});
app.ask('Your race starts by ' + localTime + 'at' + startLocation);
conv.ask(new Suggestions('End Race'));
} else { //Returned if permission not granted
conv.ask('You do not have your location on. Say "Locate me", to retrieve your location');
conv.ask(new Suggestions(['Locate me', 'Exit']));
}
});