1

我想知道是否有人可以提供帮助,因为我正在用这个把头撞到墙上。几天来我一直在寻找答案并尝试了各种方法,下面是我得到的最接近的答案。

基本上,我正在在家中建立一个供个人使用的 Alexa 技能,以向我的儿子提供奖励积分,并且它会在我们的厨房仪表板上进行更新。我可以很好地发布积分并更新仪表板(更新 firebase 数据库),但是当我问 alexa 他有多少时我无法获得积分。我的代码如下。

const GetPointsHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest'
      && request.intent.name === 'HowManyPointsDoesNameHaveIntent';
  },
  handle(handlerInput) {

      var options = {
        "method": "GET",
        "hostname": "blah-blah-blah.firebaseio.com",
        "port": null,
        "path": "/users/Connor/points.json",
        "headers": {
          "cache-control": "no-cache"
        }
      };

      var req = https.request(options, function (res) {
        var chunks = [];

        res.on("data", function (chunk) {
          chunks.push(chunk);
        });

        res.on("end", function () {
          var body = Buffer.concat(chunks);
          //console.log(body.toString());
          total = body.toString();

        });
    });

    req.end();

    speechOutput = "Connor has " + total + " points";

    return handlerInput.responseBuilder
      .speak(speechOutput)
      .getResponse();
  },
};

我问 alexa 的那一刻的结果是“康纳有未定义的点”,但是如果我立即再次问,它工作正常。

当我在浏览器中加载它时,json 端点实际上只是显示了它的值,所以不需要深入研究我不认为的响应。

我知道请求模块应该更容易,但是如果我使用 VS 代码命令行安装它并上传函数,因为文件变得如此大,包含所有模块依赖项,我不能再在线编辑函数了超过大小限制,所以如果可能的话要避免这种情况。

我知道这个函数会更好地作为一个助手,一旦我开始工作,我就会这样做。我不需要这个特别漂亮,只需要它工作。

4

2 回答 2

2

Node.js 默认是异步的,这意味着您的响应构建器在 GET 请求完成之前被调用。

解决方案:使用async-await,类似这样的东西

async handle(handlerInput) {

      var options = {
        "method": "GET",
        "hostname": "blah-blah-blah.firebaseio.com",
        "port": null,
        "path": "/users/Connor/points.json",
        "headers": {
          "cache-control": "no-cache"
        }
      };

      var req = await https.request(options, function (res) {
        var chunks = [];

        res.on("data", function (chunk) {
          chunks.push(chunk);
        });

        res.on("end", function () {
          var body = Buffer.concat(chunks);
          //console.log(body.toString());
          total = body.toString();

        });
    });

    req.end();

    speechOutput = "Connor has " + total + " points";

    return handlerInput.responseBuilder
      .speak(speechOutput)
      .getResponse();
  },

如果这不起作用,请告诉我。还可以开发个人使用的 alexa 技能,查看alexa 蓝图

于 2018-10-13T09:52:41.523 回答
1

这是因为 nodejs 的异步行为。Node 不会等待您的http请求完成。因此, speechOutput = "Connor has " + total + " points";甚至在获取的值之前就执行total了。因此,undefined

要完成这项工作,您必须使用Promises. 编写一个单独的函数来触发http请求。检查此PetMatchSkill并查看它是如何完成的。您可以将其用作任何请求的常用方法。

前任:

function httpGet(options) {
  return new Promise(((resolve, reject) => {
    const request = https.request(options, (response) => {
      response.setEncoding('utf8');
      let returnData = '';    
      if (response.statusCode < 200 || response.statusCode >= 300) {
        return reject(new Error(`${response.statusCode}: ${response.req.getHeader('host')} ${response.req.path}`));
      }    
      response.on('data', (chunk) => {
        returnData += chunk;
      });    
      response.on('end', () => {
        resolve(JSON.parse(returnData));
      });    
      response.on('error', (error) => {
        reject(error);
      });
    });
    request.end();
  }));
}

现在在您的意图处理程序中使用async- await

async handle(handlerInput) {
   var options = {
        "method": "GET",
        "hostname": "blah-blah-blah.firebaseio.com",
        "port": null,
        "path": "/users/Connor/points.json",
        "headers": {
          "cache-control": "no-cache"
        }
      };
   const response = await httpGet(options);
   var total = 0;
   if (response.length > 0) {
      // do your stuff
      //total = response
   }
   speechOutput = "Connor has " + total + " points";
   return handlerInput.responseBuilder
     .speak(speechOutput)
     .getResponse();
}
于 2018-10-13T14:48:32.840 回答