Error: No response has been set. Cloud Functions for Actions on Google Assistant
Error: No response has been set. Cloud Functions for Actions on Google Assistant
我正在为 Google 主页构建一个 Assistant 应用程序,使用 Dialogflow、Cloud Functions 和新的 NodeJS 客户端 库 V2,用于 Google 上的 Actions。事实上,我正在将使用 V1 构建的旧代码迁移到 V2。
背景
我正在尝试使用两个单独的意图获取用户的位置:Request Permission
(向用户请求 triggers/send 权限的意图)和 User Info
(检查用户是否授予权限,然后 returns 助手请求的数据继续。
问题
问题是在 V1 上运行良好的相同代码在 V2 上运行不正常。所以我不得不做一些重构。当我部署我的云函数时,我能够成功请求用户的许可,获取他的位置,然后使用外部库 (geocode
),我可以将 latlong 转换为人类可读的形式。但由于某些原因(我认为它的承诺)我无法解析承诺对象并将其显示给用户
错误
我收到以下错误:
代码
下面是我的云函数代码。我尝试了此代码的多个版本,使用 request
库、https
库等。运气不好……运气不好
const {dialogflow, Suggestions,SimpleResponse,Permission} = require('actions-on-google')
const functions = require('firebase-functions');
const geocoder = require('geocoder');
const app = dialogflow({ debug: true });
app.middleware((conv) => {
conv.hasScreen =
conv.surface.capabilities.has('actions.capability.SCREEN_OUTPUT');
conv.hasAudioPlayback =
conv.surface.capabilities.has('actions.capability.AUDIO_OUTPUT');
});
function requestPermission(conv) {
conv.ask(new Permission({
context: 'To know who and where you are',
permissions: ['NAME','DEVICE_PRECISE_LOCATION']
}));
}
function userInfo ( conv, params, granted) {
if (!conv.arguments.get('PERMISSION')) {
// Note: Currently, precise locaton only returns lat/lng coordinates on phones and lat/lng coordinates
// and a geocoded address on voice-activated speakers.
// Coarse location only works on voice-activated speakers.
conv.ask(new SimpleResponse({
speech:'Sorry, I could not find you',
text: 'Sorry, I could not find you'
}))
conv.ask(new Suggestions(['Locate Me', 'Back to Menu',' Quit']))
}
if (conv.arguments.get('PERMISSION')) {
const permission = conv.arguments.get('PERMISSION'); // also retrievable with explicit arguments.get
console.log('User: ' + conv.user)
console.log('PERMISSION: ' + permission)
const location = conv.device.location.coordinates
console.log('Location ' + JSON.stringify(location))
// Reverse Geocoding
geocoder.reverseGeocode(location.latitude,location.longitude,(err,data) => {
if (err) {
console.log(err)
}
// console.log('geocoded: ' + JSON.stringify(data))
console.log('geocoded: ' + JSON.stringify(data.results[0].formatted_address))
conv.ask(new SimpleResponse({
speech:'You currently at ' + data.results[0].formatted_address + '. What would you like to do now?',
text: 'You currently at ' + data.results[0].formatted_address + '.'
}))
conv.ask(new Suggestions(['Back to Menu', 'Learn More', 'Quit']))
})
}
}
app.intent('Request Permission', requestPermission);
app.intent('User Info', userInfo);
exports.myCloudFunction = functions.https.onRequest(app);
非常感谢任何帮助。谢谢
您最后的猜测是正确的 - 您的问题是您没有使用 Promises。
如果使用异步调用,app.intent()
期望处理函数(在您的情况下为 userInfo
)return Promise。 (如果你不是,你可以 return 什么都不做。)
正常的做法是使用 returnPromise。但是,这在您的情况下很棘手,因为地理编码库尚未更新为使用 Promises,并且您在 userInfo
函数中有其他代码没有 return 任何东西。
在这种情况下重写可能看起来像这样(但是我还没有测试代码)。在其中,我将 userInfo
中的两个条件分解为另外两个函数,因此可以 return 一个 Promise。
function userInfoNotFound( conv, params, granted ){
// Note: Currently, precise locaton only returns lat/lng coordinates on phones and lat/lng coordinates
// and a geocoded address on voice-activated speakers.
// Coarse location only works on voice-activated speakers.
conv.ask(new SimpleResponse({
speech:'Sorry, I could not find you',
text: 'Sorry, I could not find you'
}))
conv.ask(new Suggestions(['Locate Me', 'Back to Menu',' Quit']))
}
function userInfoFound( conv, params, granted ){
const permission = conv.arguments.get('PERMISSION'); // also retrievable with explicit arguments.get
console.log('User: ' + conv.user)
console.log('PERMISSION: ' + permission)
const location = conv.device.location.coordinates
console.log('Location ' + JSON.stringify(location))
return new Promise( function( resolve, reject ){
// Reverse Geocoding
geocoder.reverseGeocode(location.latitude,location.longitude,(err,data) => {
if (err) {
console.log(err)
reject( err );
} else {
// console.log('geocoded: ' + JSON.stringify(data))
console.log('geocoded: ' + JSON.stringify(data.results[0].formatted_address))
conv.ask(new SimpleResponse({
speech:'You currently at ' + data.results[0].formatted_address + '. What would you like to do now?',
text: 'You currently at ' + data.results[0].formatted_address + '.'
}))
conv.ask(new Suggestions(['Back to Menu', 'Learn More', 'Quit']))
resolve()
}
})
});
}
function userInfo ( conv, params, granted) {
if (conv.arguments.get('PERMISSION')) {
return userInfoFound( conv, params, granted );
} else {
return userInfoNotFound( conv, params, granted );
}
}
多亏了@Prisoner,我才能够让它发挥作用。我不必修改我的 Dialogflow 结构或任何东西。我所要做的就是将反向地理编码部分更改为@Prisoner 建议的内容。它对我有用。
//Reverse Geocoding
return new Promise( function( resolve, reject ){
// Reverse Geocoding
geocoder.reverseGeocode(location.latitude,location.longitude,(err,data) => {
if (err) {
console.log(err)
reject( err );
} else {
// console.log('geocoded: ' + JSON.stringify(data))
console.log('geocoded: ' + JSON.stringify(data.results[0].formatted_address))
conv.ask(new SimpleResponse({
speech:'You currently at ' + data.results[0].formatted_address + '. What would you like to do now?',
text: 'You currently at ' + data.results[0].formatted_address + '.'
}))
conv.ask(new Suggestions(['Back to Menu', 'Learn More', 'Quit']))
resolve()
}
})
});
我现在可以继续做其他事情了!
我正在为 Google 主页构建一个 Assistant 应用程序,使用 Dialogflow、Cloud Functions 和新的 NodeJS 客户端 库 V2,用于 Google 上的 Actions。事实上,我正在将使用 V1 构建的旧代码迁移到 V2。
背景
我正在尝试使用两个单独的意图获取用户的位置:Request Permission
(向用户请求 triggers/send 权限的意图)和 User Info
(检查用户是否授予权限,然后 returns 助手请求的数据继续。
问题
问题是在 V1 上运行良好的相同代码在 V2 上运行不正常。所以我不得不做一些重构。当我部署我的云函数时,我能够成功请求用户的许可,获取他的位置,然后使用外部库 (geocode
),我可以将 latlong 转换为人类可读的形式。但由于某些原因(我认为它的承诺)我无法解析承诺对象并将其显示给用户
错误
我收到以下错误:
代码
下面是我的云函数代码。我尝试了此代码的多个版本,使用 request
库、https
库等。运气不好……运气不好
const {dialogflow, Suggestions,SimpleResponse,Permission} = require('actions-on-google')
const functions = require('firebase-functions');
const geocoder = require('geocoder');
const app = dialogflow({ debug: true });
app.middleware((conv) => {
conv.hasScreen =
conv.surface.capabilities.has('actions.capability.SCREEN_OUTPUT');
conv.hasAudioPlayback =
conv.surface.capabilities.has('actions.capability.AUDIO_OUTPUT');
});
function requestPermission(conv) {
conv.ask(new Permission({
context: 'To know who and where you are',
permissions: ['NAME','DEVICE_PRECISE_LOCATION']
}));
}
function userInfo ( conv, params, granted) {
if (!conv.arguments.get('PERMISSION')) {
// Note: Currently, precise locaton only returns lat/lng coordinates on phones and lat/lng coordinates
// and a geocoded address on voice-activated speakers.
// Coarse location only works on voice-activated speakers.
conv.ask(new SimpleResponse({
speech:'Sorry, I could not find you',
text: 'Sorry, I could not find you'
}))
conv.ask(new Suggestions(['Locate Me', 'Back to Menu',' Quit']))
}
if (conv.arguments.get('PERMISSION')) {
const permission = conv.arguments.get('PERMISSION'); // also retrievable with explicit arguments.get
console.log('User: ' + conv.user)
console.log('PERMISSION: ' + permission)
const location = conv.device.location.coordinates
console.log('Location ' + JSON.stringify(location))
// Reverse Geocoding
geocoder.reverseGeocode(location.latitude,location.longitude,(err,data) => {
if (err) {
console.log(err)
}
// console.log('geocoded: ' + JSON.stringify(data))
console.log('geocoded: ' + JSON.stringify(data.results[0].formatted_address))
conv.ask(new SimpleResponse({
speech:'You currently at ' + data.results[0].formatted_address + '. What would you like to do now?',
text: 'You currently at ' + data.results[0].formatted_address + '.'
}))
conv.ask(new Suggestions(['Back to Menu', 'Learn More', 'Quit']))
})
}
}
app.intent('Request Permission', requestPermission);
app.intent('User Info', userInfo);
exports.myCloudFunction = functions.https.onRequest(app);
非常感谢任何帮助。谢谢
您最后的猜测是正确的 - 您的问题是您没有使用 Promises。
如果使用异步调用,app.intent()
期望处理函数(在您的情况下为 userInfo
)return Promise。 (如果你不是,你可以 return 什么都不做。)
正常的做法是使用 returnPromise。但是,这在您的情况下很棘手,因为地理编码库尚未更新为使用 Promises,并且您在 userInfo
函数中有其他代码没有 return 任何东西。
在这种情况下重写可能看起来像这样(但是我还没有测试代码)。在其中,我将 userInfo
中的两个条件分解为另外两个函数,因此可以 return 一个 Promise。
function userInfoNotFound( conv, params, granted ){
// Note: Currently, precise locaton only returns lat/lng coordinates on phones and lat/lng coordinates
// and a geocoded address on voice-activated speakers.
// Coarse location only works on voice-activated speakers.
conv.ask(new SimpleResponse({
speech:'Sorry, I could not find you',
text: 'Sorry, I could not find you'
}))
conv.ask(new Suggestions(['Locate Me', 'Back to Menu',' Quit']))
}
function userInfoFound( conv, params, granted ){
const permission = conv.arguments.get('PERMISSION'); // also retrievable with explicit arguments.get
console.log('User: ' + conv.user)
console.log('PERMISSION: ' + permission)
const location = conv.device.location.coordinates
console.log('Location ' + JSON.stringify(location))
return new Promise( function( resolve, reject ){
// Reverse Geocoding
geocoder.reverseGeocode(location.latitude,location.longitude,(err,data) => {
if (err) {
console.log(err)
reject( err );
} else {
// console.log('geocoded: ' + JSON.stringify(data))
console.log('geocoded: ' + JSON.stringify(data.results[0].formatted_address))
conv.ask(new SimpleResponse({
speech:'You currently at ' + data.results[0].formatted_address + '. What would you like to do now?',
text: 'You currently at ' + data.results[0].formatted_address + '.'
}))
conv.ask(new Suggestions(['Back to Menu', 'Learn More', 'Quit']))
resolve()
}
})
});
}
function userInfo ( conv, params, granted) {
if (conv.arguments.get('PERMISSION')) {
return userInfoFound( conv, params, granted );
} else {
return userInfoNotFound( conv, params, granted );
}
}
多亏了@Prisoner,我才能够让它发挥作用。我不必修改我的 Dialogflow 结构或任何东西。我所要做的就是将反向地理编码部分更改为@Prisoner 建议的内容。它对我有用。
//Reverse Geocoding
return new Promise( function( resolve, reject ){
// Reverse Geocoding
geocoder.reverseGeocode(location.latitude,location.longitude,(err,data) => {
if (err) {
console.log(err)
reject( err );
} else {
// console.log('geocoded: ' + JSON.stringify(data))
console.log('geocoded: ' + JSON.stringify(data.results[0].formatted_address))
conv.ask(new SimpleResponse({
speech:'You currently at ' + data.results[0].formatted_address + '. What would you like to do now?',
text: 'You currently at ' + data.results[0].formatted_address + '.'
}))
conv.ask(new Suggestions(['Back to Menu', 'Learn More', 'Quit']))
resolve()
}
})
});
我现在可以继续做其他事情了!