Как правильно использовать асинхронные функции в навыке Alexa?

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

    const getParkingSpots_Handler =  {
        canHandle(handlerInput) {
            const request = handlerInput.requestEnvelope.request;
            return request.type === 'IntentRequest' && request.intent.name === 'getParkingSpots' ;
        },
        handle(handlerInput) {
            const request = handlerInput.requestEnvelope.request;
            const responseBuilder = handlerInput.responseBuilder;
            let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();

            let requestData = {
                // I can't show this sorry
                }

            let options = {
               // I can't show this sorry
            };

            // Call to the API
            const postAxios = async () => {
                try {
                    const response = await axios.post(API_URL, requestData, options);
                    return response.data.result;
                } catch(error) {
                    console.log(error);
                }
            };

            // Another function. This is where I use the data from the API response. I intent to add some code here that only picks out a number of results, sorts it by price etc. etc.
            const useTheResult = async () => {
                const result  = await postAxios();
                console.log('Response from the API:', result);
            };

            // We defined the functions above, now we need to execute them
            useTheResult();

            // This is what we will refer to the 'problem code'.
            let say = `Hello from confidientialCompany! You can park...`;
                return responseBuilder
                    .speak(say)
                    .reprompt('try again, ' + say)
                    .getResponse();
        },
    };

В идеале, когда я добавляю код для изменения ответа в useTheResult, я хочу, чтобы код проблемы также находился внутри useTheResult... почему? Потому что, как только я выберу нужные мне данные и изменю их, я попытаюсь превратить say в «удобочитаемое для Alexa» предложение, например:

    let say = `Hello from confidentialCompany! You can park on ${roadName1}, ${roadName2} and ${roadName3}. Prices start from ${startingPrice} pounds.`

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


person user12558632    schedule 04.06.2020    source источник


Ответы (1)


Добавьте ключевое слово async к имени метода handle и используйте await внутри:

const getParkingSpots_Handler =  {
        canHandle(handlerInput) {
            const request = handlerInput.requestEnvelope.request;
            return request.type === 'IntentRequest' && request.intent.name === 'getParkingSpots' ;
        },
        async handle(handlerInput) {
            const request = handlerInput.requestEnvelope.request;
            const responseBuilder = handlerInput.responseBuilder;
            let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();

            let requestData = {
                // I can't show this sorry
                }

            let options = {
               // I can't show this sorry
            };

            // Call to the API
             let result = null;
             try {
                 const response = await axios.post(API_URL, requestData, options);
                 result = response.data.result;
             } catch(error) {
                 // handle this case and return some message to User
                 console.log(error);
             }
            
            // assume your data structure to be like:
            /**
             result: {
               roadName1: "1st street",
               roadName2: "2nd street",
               roadName3: "3rd street", 
               startingPrice: "1.2"
             }
            */
            const {roadName1, roadName2, roadName3, startingPrice} = result;

            // This is what we will refer to the 'problem code'.
            let say = `Hello from confidentialCompany! You can park on ${roadName1}, ${roadName2} and ${roadName3}. Prices start from ${startingPrice} pounds.`;
                return responseBuilder
                    .speak(say)
                    .reprompt('try again, ' + say)
                    .getResponse();
        },
    };

Если вы хотите сделать больше вызовов в одной и той же функции:

try {
   const [response1, response2] = await Promise.all([
      axios.post(API_URL1, requestData, options),
      axios.post(API_URL2, requestData, options)
   ]);
   // do things with your responses
   // ...
} catch(error) {
   // handle this case and return some message to User
   console.log(error);
}
person slawciu    schedule 04.06.2020
comment
Спасибо за ваш ответ. Там, где вы написали const {roadName1, roadName2, roadName3, startingPrice} = result; Это использование деструктуризации? - person user12558632; 12.06.2020
comment
Извините за возрождение этого мертвого вопроса, но что, если я хочу сделать еще один вызов другого API и в основном сделать то же самое, что и раньше, все в той же асинхронной функции? - person user12558632; 22.07.2020
comment
Я отредактировал ответ. Вы должны использовать Promise.all, если второй вызов не зависит от первого. В противном случае просто вызовите второй API так же, как вы вызвали первый. Подробнее о Promise.all можно прочитать здесь developer.mozilla .org/en-US/docs/Web/JavaScript/Reference/ - person slawciu; 22.07.2020