action-on-google v1-> v2迁移:"错误:已发送响应"

时间:2018-03-21 17:13:09

标签: actions-on-google

我从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的请求(使用请求库)可以被视为“响应”。可能导致这个错误?

也许它是conv.close()元素中简单响应的格式?

知道为什么会出现这种错误吗?

干杯

编辑:

认为我需要开始使用异步代码&amp;承诺像这个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')
    })
})

1 个答案:

答案 0 :(得分:2)

为了鼓励最佳实践,v2客户端库需要使用Promises来执行异步请求。

响应生成的工作原理是它将在IntentHandler函数执行结束时生成并发送响应,除非函数返回Promise,然后它将等到{{1}然后解析然后发送响应。

您可以查看v2.0.0-alpha分支中包含的Name Psychic sample以查看工作示例:

Promise

app.intent('handle_permission', (conv, params, permissionGranted) => { // ... return coordinatesToCity(coordinates.latitude, coordinates.longitude) .then(city => { conv.user.storage.location = city showLocationOnScreen(conv) }) // ... } 这是一个返回coordinatesToCity

的函数

Promise这是一个调用showLocationOnScreenconv.ask并生成回复的函数。

conv.close

如果您的Node.js版本支持异步等待(我认为默认情况下启动Node.js 7.6+,但为了安全使用Node.js 8+),那么您可以简化代码以不链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, })) }

.then

请注意Firebase功能当前使用Node.js 6并且当前不支持支持异步等待,因此您需要一个转发器才能在那里使用它。