如何在其他Handler中调用HelloWorldIntentHandler内的team1、team2、server变量
如何在Alexa技能的不同Intent Handler之间共享变量?
你当前的问题在于,HelloWorldIntentHandler里的team1、team2、server都是局部变量,作用域仅限于它的handle方法内部,PickleballScoreNowHandler根本没法直接访问这些值。要在不同Intent之间共享数据,得用Alexa技能框架提供的会话属性(Session Attributes)或者持久化属性(Persistent Attributes),下面给你具体的实现方案:
方案一:使用会话属性(当前会话内有效)
会话属性会在用户和技能的整个交互会话中保留,只要会话没结束,其他Intent都能读取这些数据。
1. 在HelloWorldIntentHandler中存储变量到会话属性
修改HelloWorldIntentHandler的handle方法,把需要共享的变量存到会话属性里:
const HelloWorldIntentHandler = { canHandle(handlerInput) { return handlerInput.requestEnvelope.request.type === 'IntentRequest' && handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent'; }, handle(handlerInput) { // 获取槽位值 const team1 = handlerInput.requestEnvelope.request.intent.slots.score.value; const team2 = handlerInput.requestEnvelope.request.intent.slots.scoreone.value; const server = handlerInput.requestEnvelope.request.intent.slots.scoretwo.value; const value1 = Number(team1); const value2 = Number(team2); const totalteam1 = Math.round(value1 + value1 ); const totalteam2 = Math.round(value2 + value2 ); // 从属性管理器获取会话属性,存入需要共享的变量 const sessionAttributes = handlerInput.attributesManager.getSessionAttributes(); sessionAttributes.team1 = team1; sessionAttributes.team2 = team2; sessionAttributes.server = server; // 如果你需要共享计算后的总分,也可以一起存 sessionAttributes.totalteam1 = totalteam1; sessionAttributes.totalteam2 = totalteam2; handlerInput.attributesManager.setSessionAttributes(sessionAttributes); return handlerInput.responseBuilder .speak("score is " + totalteam1) .reprompt() .getResponse(); } };
2. 在PickleballScoreNowHandler中读取会话属性的值
修改PickleballScoreNowHandler的handle方法,从会话属性中取出之前存储的变量:
const PickleballScoreNowHandler = { canHandle(handlerInput) { return handlerInput.requestEnvelope.request.type === 'IntentRequest' && handlerInput.requestEnvelope.request.intent.name === 'PickleballScoreNow'; }, handle(handlerInput) { // 获取会话属性里的变量 const sessionAttributes = handlerInput.attributesManager.getSessionAttributes(); const team1 = sessionAttributes.team1; const team2 = sessionAttributes.team2; const server = sessionAttributes.server; // 要处理变量不存在的情况(比如用户直接调用这个Intent而没先触发HelloWorldIntent) let speechText; if (team1 && team2 && server) { speechText = `score is ${team1} ${team2} ${server}`; } else { speechText = "我还没有获取到比分信息,请先告诉我初始比分哦!"; } return handlerInput.responseBuilder .speak(speechText) .reprompt() .getResponse(); } };
方案二:使用持久化属性(跨会话保存数据)
如果需要让数据在用户关闭技能再打开后依然保留,就用持久化属性。用法和会话属性类似,但需要额外保存操作:
1. 在HelloWorldIntentHandler中存储并保存持久化属性
注意这里handle方法要改成async,因为保存属性是异步操作:
const HelloWorldIntentHandler = { canHandle(handlerInput) { return handlerInput.requestEnvelope.request.type === 'IntentRequest' && handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent'; }, async handle(handlerInput) { // 获取槽位值 const team1 = handlerInput.requestEnvelope.request.intent.slots.score.value; const team2 = handlerInput.requestEnvelope.request.intent.slots.scoreone.value; const server = handlerInput.requestEnvelope.request.intent.slots.scoretwo.value; const value1 = Number(team1); const value2 = Number(team2); const totalteam1 = Math.round(value1 + value1 ); const totalteam2 = Math.round(value2 + value2 ); // 获取并设置持久化属性 const persistentAttributes = handlerInput.attributesManager.getPersistentAttributes(); persistentAttributes.team1 = team1; persistentAttributes.team2 = team2; persistentAttributes.server = server; handlerInput.attributesManager.setPersistentAttributes(persistentAttributes); // 异步保存属性 await handlerInput.attributesManager.savePersistentAttributes(); return handlerInput.responseBuilder .speak("score is " + totalteam1) .reprompt() .getResponse(); } };
2. 在PickleballScoreNowHandler中读取持久化属性
const PickleballScoreNowHandler = { canHandle(handlerInput) { return handlerInput.requestEnvelope.request.type === 'IntentRequest' && handlerInput.requestEnvelope.request.intent.name === 'PickleballScoreNow'; }, handle(handlerInput) { // 获取持久化属性 const persistentAttributes = handlerInput.attributesManager.getPersistentAttributes(); const team1 = persistentAttributes.team1; const team2 = persistentAttributes.team2; const server = persistentAttributes.server; // 同样处理变量不存在的情况 let speechText; if (team1 && team2 && server) { speechText = `score is ${team1} ${team2} ${server}`; } else { speechText = "我还没有获取到比分信息,请先告诉我初始比分哦!"; } return handlerInput.responseBuilder .speak(speechText) .reprompt() .getResponse(); } };
为什么原来的方法不行?
你之前在HelloWorldIntentHandler里定义的var team1这些变量,都是handle方法内部的局部变量,作用域只限于这个方法。每个Intent Handler都是独立的对象,它们的handle方法之间没有直接的作用域关联,所以另一个Handler根本看不到这些变量。必须通过Alexa提供的属性管理机制,把数据存到框架维护的属性容器里,才能实现跨Intent共享。
内容的提问来源于stack exchange,提问作者j4520
相关产品推荐
相关产品推荐

