HTTP-запрос с Alexa и Lambda на SDK v2, как это сделать? - PullRequest
0 голосов
/ 01 мая 2018

Я играю с ASK SDK v2, предоставленной Amazon, чтобы сделать Skill для Alexa, но я столкнулся с архитектурной проблемой:

Прежде всего, HTTP-запрос работает как чудо, но я хотел бы вернуть речевой ответ, если и только если мой HTTP-запрос завершен, но я даже не знаю, возможно ли это из-за функции «handle», которая должна верните что-нибудь (посмотрите на комментарии):

const MyIntentHandler = {

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

    var options = {
      host: 'http://foo.com',
      port: 80,
      path: '/mypath',
      method: 'GET'
    };

    var req = http.request(options, function(result){
      result.on("end", function(){
        //I would like to return speak here like that :
        //return handlerInput.responseBuilder.speak("It works").withSimpleCard("MyTestApp", "It works").getResponse()
      })
    });
    req.end();
    //And I would like to remove this line to manage response in result.on("end", function(){}) above
    return handlerInput.responseBuilder.speak("It works").withSimpleCard("MyTestApp", "It works").getResponse();
  },
};

Есть идеи с этим справиться?

Ответы [ 3 ]

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

Также мы можем использовать модуль запроса для вызова API следующим образом

const SearchIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      handlerInput.requestEnvelope.request.intent.name === "SearchIntent"
    );
  },
  handle(handlerInput) {
    const query = handlerInput.requestEnvelope.request.intent.slots.SearchQuery.value;
    return new Promise((resolve, reject) => {
      getSearchResults(query).then((response) => {
        resolve(handlerInput.responseBuilder.speak(response).getResponse());
      }).catch((error) => {
        resolve(handlerInput.responseBuilder.speak('This is not available at the moment.').getResponse());
      });
    });
  }
};


function getSearchResults(query){
  return new Promise((resolve, reject)=>{
    let options = { 
      method: 'POST',
      url: 'http://url.com',
      headers: {'Cache-Control': 'no-cache','Content-Type': 'application/x-www-form-urlencoded' },
      form: { text: query } 
    };
    request(options, function (error, response, body) {
      if (error) throw new Error(error);
      let data = body ? JSON.parse(body) : ""
      return resolve(data);
    });
  });
}
0 голосов
/ 25 октября 2018

Пример Async / Await

  1. Преобразование handle в асинхронную функцию.
  2. Жду вашего обещания

Пример:

const SomeIntentHandler = {
  canHandle(handlerInput) {...},
  async handle(handlerInput) {
    return handlerInput.responseBuilder.speak(await promise).getResponse();
  }
};
0 голосов
/ 02 мая 2018

Я нашел официальный способ сделать это:

1) Создайте новую функцию, управляющую запросом http и верните обещание:

function httpGet(options) {
  return new Promise(((resolve, reject) => {

    const request = http.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.on('error', function (error) {
      reject(error);
    });
    
    request.end();
  }));
}

2) В Intent верните обещание, в котором вы вызываете функцию httpGet:

const MyIntentHandler = {

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

    var options = {
      host: 'http://foo.com',
      port: 80,
      path: '/mypath',
      method: 'GET'
    };

    return new Promise((resolve, reject) => {
     httpGet(options).then((response) => {
       resolve(handlerInput.responseBuilder.speak("It is done.").getResponse());
     }).catch((error) => {
        resolve(handlerInput.responseBuilder.speak('Thor is not available at the moment. Please try again later or contact your administrator.')
        .getResponse());
      });
    });
  },
};

Это способ сделать это правильно. Мой пример основан на alexa petmatch sample .

...