【问题标题】:Lambda function not returning response to Alexa skillLambda 函数未返回对 Alexa 技能的响应
【发布时间】:2019-03-15 16:09:32
【问题描述】:

我有一个用 Nodejs 编写的 Alexa 技能的 Lambda 函数。它对服务进行 HTTP 调用并将输出返回给 Alexa Skill。调用技能时,将调用 lambda,并进行 HTTP 调用。但是,在返回 HTTP 响应之前,lambda 会返回,因此该技能没有得到答案。

下面是我的 Lambda 函数

var Alexa = require('ask-sdk');
var http = require('http');
var SKILL_NAME = 'Some Facts';

var GetNewFactHandler = {
  canHandle(handlerInput) {
  var request = handlerInput.requestEnvelope.request;
  return request.type === 'LaunchRequest'
  || (request.type === 'IntentRequest'
    && request.intent.name === 'GetNewFactIntent');
},
handle(handlerInput) {
    getTop("", (data)=>{
    let speechOutput = "The result is " + data;
        console.log("resp from lambda ", speechOutput)
        var respSpeak =  handlerInput.responseBuilder
        .speak(speechOutput)
        .withSimpleCard(SKILL_NAME, data)
        .getResponse();
        console.log("respSpeak ", respSpeak);
        return respSpeak;
    });
  },
};


function getTop(query, callback) {
   var options = {
        host: 'somehost',
        port: '8100',
        path: '/top',
        method: 'GET',
   };

    var req = http.request(options, res => {
        res.setEncoding('utf8');
        var responseString = "";

        res.on('data', chunk => {
            responseString = responseString + chunk;
        });

        res.on('end', () => {
            console.log("********",JSON.parse(responseString).Name);
            let respStr = JSON.parse(responseString).Name;
            callback(respStr);
        });

    });
    req.end();
}

在 lambda 日志中,我可以看到 getTop() 中的日志。但是 lambda 的响应在收到 HTTP 调用的响应之前返回。我在想,在回调中构建响应将确保仅在 HTTP 调用完成后才返回响应。但情况似乎并非如此。如何解决这个问题?任何帮助表示赞赏。

【问题讨论】:

  • 根据您使用的节点版本,您需要将 Promise 与 .then 和 .catch 或更新的 async 和 await 一起使用,您的问题是 JS 异步运行,因此对端点的调用发生在您的函数正在寻找数据以解决 GetNewFact 意图的同时。有很多关于如何实现这一点以使您的功能正常工作的好文档。

标签: node.js aws-lambda alexa-skills-kit alexa-skill


【解决方案1】:

Node.js 默认是异步,这意味着在服务返回数据之前调用您的响应构建器。 我在调用客户资料 api 以获取电话号码时遇到了类似的问题,我使用 async-await 解决了这个问题

async handle(handlerInput) {
    const { serviceClientFactory, responseBuilder } = handlerInput;
    try {
      const upsServiceClient = serviceClientFactory.getUpsServiceClient();
      const profileMobileObject = await upsServiceClient.getProfileMobileNumber();
     
      const profileMobile = profileMobileObject.phoneNumber;
      const speechResponse = `Hello your mobile number is, ${profileMobile}</say-as>`;
      const cardResponse = `Hello your mobile number is, ${profileMobile}`
      return responseBuilder
                      .speak(speechResponse)
                      .withSimpleCard(APP_NAME, cardResponse)
                      .getResponse();
    } catch (error) {
      console.log(JSON.stringify(error));
      if (error.statusCode == 403) {
        return responseBuilder
        .speak(messages.NOTIFY_MISSING_PERMISSIONS)
        .withAskForPermissionsConsentCard([MOBILE_PERMISSION])
        .getResponse();
      }
      console.log(JSON.stringify(error));
      const response = responseBuilder.speak(messages.ERROR).getResponse();
      return response;
    }
  },

在调用服务之前使函数async并使用await。 您也可以通过 Promises

进行此操作

【讨论】:

  • 谢谢,这也是我最终做的。使用 async-await 并且效果很好!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-24
  • 2018-06-09
  • 1970-01-01
  • 2020-10-15
  • 1970-01-01
  • 2019-01-23
  • 1970-01-01
相关资源
最近更新 更多