actions-on-google v1->v2 migration: "Error: Response has already been sent"
actions-on-google v1->v2 migration: "Error: Response has already been sent"
我正在从 v1 迁移到 v2 alpha,但出现以下错误:
Error: Response has already been sent. Is this being used in an async call that was not returned as a promise to the action/intent handler?
at DialogflowConversation.add (/user_code/node_modules/actions-on-google/dist/service/actionssdk/conversation/conversation.js:51:19)
at DialogflowConversation.close (/user_code/node_modules/actions-on-google/dist/service/actionssdk/conversation/conversation.js:66:21)
at Request.err [as _callback] (/user_code/index.js:1141:20)
at Request.self.callback (/user_code/node_modules/request/request.js:186:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/user_code/node_modules/request/request.js:1163:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at IncomingMessage.<anonymous> (/user_code/node_modules/request/request.js:1085:12)
来源:
try {
conv.close(new SimpleResponse({
// Sending the details to the user
speech: textToSpeech1,
text: displayText1
}))
} catch (err) {
if(err instanceof Error) {
console.error(err);
} else {
console.error(new Error(err));
}
}
代码位置:https://github.com/BTS-CM/BeyondBitshares-Firebase/blob/master/index_v2.js#L1141
我不明白为什么会出现上述错误,此时我还没有向用户发送响应。也许对外部 REST API(使用请求库)的请求可以算作 'Response' 可能导致此错误?
也许这是 conv.close() 元素中简单响应的格式?
知道为什么会出现此错误吗?
干杯
编辑:
我认为我需要开始使用像这个 v2 片段这样的异步代码和承诺吗?它似乎在 REST API 查询开始之前响应空白..
app.intent('tell_greeting', conv => {
// Return a promise to do async asks, will send everything when promise resolves
return new Promise(resolve => setTimeout(() => resolve(), 1000))
.then(() => {
conv.ask('Hi')
})
})
为鼓励最佳实践,v2 客户端库需要使用 Promises 来执行异步请求。
响应生成的工作原理是它将在 IntentHandler
函数执行结束时生成并发送响应,除非函数 returns a Promise
,然后它将等待 Promise
解决然后发送响应。
您可以查看 v2.0.0-alpha 分支中包含的 Name Psychic sample 以查看工作示例:
app.intent('handle_permission', (conv, params, permissionGranted) => {
// ...
return coordinatesToCity(coordinates.latitude, coordinates.longitude)
.then(city => {
conv.user.storage.location = city
showLocationOnScreen(conv)
})
// ...
}
coordinatesToCity
这里是一个 returns 一个 Promise
.
的函数
showLocationOnScreen
这里是调用 conv.ask
或 conv.close
并生成响应的函数。
const showLocationOnScreen = conv => {
const capability = 'actions.capability.SCREEN_OUTPUT'
if (conv.surface.capabilities.has(capability) ||
!conv.available.surfaces.capabilities.has(capability)) {
return conv.close(...responses.sayLocation(conv.user.storage.location))
}
conv.ask(new NewSurface({
context: responses.newSurfaceContext,
notification: responses.notificationText,
capabilities: capability,
}))
}
如果你的 Node.js 版本支持 async await(我认为默认从 Node.js 7.6+ 开始,但为了安全起见使用 Node.js 8+),那么你可以简化代码不链接 .then
:
app.intent('handle_permission', async (conv, params, permissionGranted) => {
// ...
const city = await coordinatesToCity(coordinates.latitude, coordinates.longitude)
conv.user.storage.location = city
return showLocationOnScreen(conv)
// ...
}
请注意,Firebase Functions 当前使用 Node.js 6,而 目前不支持 异步等待,因此您需要一个转译器才能在那里使用它。
我正在从 v1 迁移到 v2 alpha,但出现以下错误:
Error: Response has already been sent. Is this being used in an async call that was not returned as a promise to the action/intent handler?
at DialogflowConversation.add (/user_code/node_modules/actions-on-google/dist/service/actionssdk/conversation/conversation.js:51:19)
at DialogflowConversation.close (/user_code/node_modules/actions-on-google/dist/service/actionssdk/conversation/conversation.js:66:21)
at Request.err [as _callback] (/user_code/index.js:1141:20)
at Request.self.callback (/user_code/node_modules/request/request.js:186:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/user_code/node_modules/request/request.js:1163:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at IncomingMessage.<anonymous> (/user_code/node_modules/request/request.js:1085:12)
来源:
try {
conv.close(new SimpleResponse({
// Sending the details to the user
speech: textToSpeech1,
text: displayText1
}))
} catch (err) {
if(err instanceof Error) {
console.error(err);
} else {
console.error(new Error(err));
}
}
代码位置:https://github.com/BTS-CM/BeyondBitshares-Firebase/blob/master/index_v2.js#L1141
我不明白为什么会出现上述错误,此时我还没有向用户发送响应。也许对外部 REST API(使用请求库)的请求可以算作 'Response' 可能导致此错误?
也许这是 conv.close() 元素中简单响应的格式?
知道为什么会出现此错误吗?
干杯
编辑:
我认为我需要开始使用像这个 v2 片段这样的异步代码和承诺吗?它似乎在 REST API 查询开始之前响应空白..
app.intent('tell_greeting', conv => {
// Return a promise to do async asks, will send everything when promise resolves
return new Promise(resolve => setTimeout(() => resolve(), 1000))
.then(() => {
conv.ask('Hi')
})
})
为鼓励最佳实践,v2 客户端库需要使用 Promises 来执行异步请求。
响应生成的工作原理是它将在 IntentHandler
函数执行结束时生成并发送响应,除非函数 returns a Promise
,然后它将等待 Promise
解决然后发送响应。
您可以查看 v2.0.0-alpha 分支中包含的 Name Psychic sample 以查看工作示例:
app.intent('handle_permission', (conv, params, permissionGranted) => {
// ...
return coordinatesToCity(coordinates.latitude, coordinates.longitude)
.then(city => {
conv.user.storage.location = city
showLocationOnScreen(conv)
})
// ...
}
coordinatesToCity
这里是一个 returns 一个 Promise
.
showLocationOnScreen
这里是调用 conv.ask
或 conv.close
并生成响应的函数。
const showLocationOnScreen = conv => {
const capability = 'actions.capability.SCREEN_OUTPUT'
if (conv.surface.capabilities.has(capability) ||
!conv.available.surfaces.capabilities.has(capability)) {
return conv.close(...responses.sayLocation(conv.user.storage.location))
}
conv.ask(new NewSurface({
context: responses.newSurfaceContext,
notification: responses.notificationText,
capabilities: capability,
}))
}
如果你的 Node.js 版本支持 async await(我认为默认从 Node.js 7.6+ 开始,但为了安全起见使用 Node.js 8+),那么你可以简化代码不链接 .then
:
app.intent('handle_permission', async (conv, params, permissionGranted) => {
// ...
const city = await coordinatesToCity(coordinates.latitude, coordinates.longitude)
conv.user.storage.location = city
return showLocationOnScreen(conv)
// ...
}
请注意,Firebase Functions 当前使用 Node.js 6,而 目前不支持 异步等待,因此您需要一个转译器才能在那里使用它。