Amazon Alexa Skill Lambda Node JS - HETP GET не работает

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

По сути, я создаю навык 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 ответа

Решение

Это из-за асинхронного поведения 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();
}

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

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

Другие вопросы по тегам