Node.js Лямбда-функция возвращает "Недопустимый ответ" обратно в Alexa Service Simulator из вызова REST.

Возникли проблемы с выполнением REST-вызова API между лямбда-функцией node.js и Alexa. Я использую библиотеку запросов, чтобы совершать звонки с привязанным аккаунтом. Я установил только один пример высказывания для намерения, и симулятор видит это прекрасно.

Кроме того, в журналах cloudwatch показан код ответа 200 от конечной точки API и любые возвращенные данные из API из console.logs в CW.

'use strict';
var http = require('http');
var request = require('request');
var Alexa = require('alexa-sdk');
var APP_ID = "amzn1.ask.skill.XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX";

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.appId = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

var handlers = {
   'LaunchRequest': function () {
        this.emit(':tell', 'Hi!');
   },

   'ApiWelcomeIntent': function () {
        request('https://some.web/api', function (error, response, body) {
            if (!error && response.statusCode == 200) {
            // from within the callback, write data to response, essentially returning it.
                var speechOutput = JSON.stringify(body);
                console.log(body + " :Raw output?");
                console.log(speechOutput + ' :JSON stringified');
                console.log(response.statusCode);
                this.emit(':tell', speechOutput);
            } else {
                console.log(error + ' : ' + response.statusCode);
                this.emit(':tell', 'There was an error');
            }
        });
    },

    'AMAZON.HelpIntent': function () {} //.........And other built in intents.

    }
};

Я предполагаю, что это как-то связано с форматом speechOutput, который я прошу Алексею "испустить / рассказать"?

2 ответа

Решение

Нет, это не имеет ничего общего с форматом speechOutput. Проблема в том, что когда обратный вызов request метод выполняется, ссылка на this потерян. Чтобы решить эту проблему, сохраните ссылку на this прежде чем позвонить request (например, назначить this к переменной с именем self):

'use strict';
var http = require('http');
var request = require('request');
var Alexa = require('alexa-sdk');
var APP_ID = "amzn1.ask.skill.XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX";

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.appId = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

var handlers = {
   'LaunchRequest': function () {
        this.emit(':tell', 'Hi!');
   },

   'ApiWelcomeIntent': function () {
        self = this

        request('https://some.web/api', function (error, response, body) {
            if (!error && response.statusCode == 200) {
            // from within the callback, write data to response, essentially returning it.
                var speechOutput = JSON.stringify(body);
                console.log(body + " :Raw output?");
                console.log(speechOutput + ' :JSON stringified');
                console.log(response.statusCode);
                self.emit(':tell', speechOutput); // USE SELF HERE
            } else {
                console.log(error + ' : ' + response.statusCode);
                self.emit(':tell', 'There was an error'); // AND HERE AS WELL
            }
        });
    },

    'AMAZON.HelpIntent': function () {} //.........And other built in intents.

    }
};

Вы сталкиваетесь с проблемой только из-за асинхронного поведения вызова NodeJS и не имеют ничего общего с запросом вызова. Вы можете решить это либо с помощью обещаний, либо с помощью обратного вызова из метода. Ниже приведен фрагмент.

'use strict';
var http = require('http');
var request = require('request');
var Alexa = require('alexa-sdk');
var APP_ID = "amzn1.ask.skill.XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX";

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.appId = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

var handlers = {
   'LaunchRequest': function () {
        this.emit(':tell', 'Hi!');
   },

   'ApiWelcomeIntent': function () {
        requestAPI( (message) => {
            this.emit(':tell', message);
        });
    },
    'AMAZON.HelpIntent': function () {} //.........And other built in intents.

    }
};

function requestAPI(callback) {
    request('https://some.web/api', function (error, response, body) {
        if (!error && response.statusCode == 200) {
        // from within the callback, write data to response, essentially returning it.
            var speechOutput = JSON.stringify(body);
            console.log(body + " :Raw output?");
            console.log(speechOutput + ' :JSON stringified');
            console.log(response.statusCode);
            callback(speechOutput);
        } else {
            console.log(error + ' : ' + response.statusCode);
            callback('There was an error');
        }
    });
}
Другие вопросы по тегам