Amazon Alexa Skill Lambda Node JS - HETP GET не работает - PullRequest
0 голосов
/ 13 октября 2018

Мне интересно, может ли кто-нибудь помочь, так как я бью себя головой об стену с этим.Я искал ответы в течение нескольких дней и пробовал разные вещи, и ниже приведен самый близкий из них.

По сути, я создаю навык Alexa для личного использования в своем доме, чтобы дать призовые очки моему сыну., и это обновляет на нашей кухне приборной панели.Я могу POST очков нормально и приборной панели обновляется (обновляет базу данных Firebase), но я не могу получить очки, когда я спрашиваю Алекса, сколько у него есть.Мой код приведен ниже.

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();
  },
};

В тот момент, когда я спрашиваю Алексу, результат «Коннор имеет неопределенные точки», но затем, если я сразу же спрашиваю снова, он работает нормально.

Конечная точка json буквально просто показывает значение, когда я загружаю его в браузере, поэтому мне не нужно копаться в ответе, который я не думаю.

Я знаю, что модуль запроса должен быть проще,но если я установлю это с использованием командной строки кода VS и загрузю функцию, поскольку файл становится настолько большим со всеми зависимостями модуля, я больше не могу редактировать функцию онлайн, так как она превышает ограничение размера, поэтому хочу по возможности этого избежать.

Я знаю, что функцию лучше разместить в качестве помощника, что я сделаю, как только получу эту работу.Мне не нужно, чтобы это было особенно красиво, просто нужно, чтобы это работало.

Ответы [ 2 ]

0 голосов
/ 13 октября 2018

Это из-за асинхронного поведения nodejs.Узел не будет ждать вашего запроса 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();
}
0 голосов
/ 13 октября 2018

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();
  },

Дайте мне знать, если это не сработает.Также, чтобы развить навыки Алексы для личного использования, проверьте чертежи Алексы .

...