Как получить параметр отклонения обещания в облачной функции Google, используемой в качестве веб-крючка Dialogflow?

#javascript #node.js #google-cloud-functions #dialogflow-es #request-promise

#javascript #node.js #google-cloud-функции #dialogflow-es #запрос-обещание

Вопрос:

Я создаю чат-бота Dialogflow, который использует облачную функцию Google в качестве веб-крючка, с node.js и запрос-обещание-родной и без использования Firebase или Google Actions. Мой веб-крючок отлично работает для извлечения и возврата нужных мне данных из внешнего API (обещание разрешено), но теперь у меня возникают проблемы при попытке кодировать обработку ошибок с помощью Promise reject .

Вот фрагмент кода, показывающий, что я пытаюсь сделать. При заведомо неправильном URL-адресе код переходит к блоку .catch, даже не переходя к опции Promise reject, а в журнале облачной функции отображается сообщение об ошибке «Необработанное отклонение».

 function searchMyData(agent) {
    return new Promise((resolve, reject) => {
        var myUrl = 'deliberately wrong to trigger rejection';

        // Make the HTTP request with request-promise-native
        // https://www.npmjs.com/package/request-promise

        var options = {
            uri: myUrl,
            headers: {
                'User-Agent': 'Request-Promise-Native'
            },
            json: true
        };

        rpn(options)
            .then((json) => {
                if(json) {
                    // Whole bunch of code for getting the desired data 
                    // and resolving the Promise
                    // This part works
                    var result = agent.add('Here is your data');
                    resolve(result); // Promise resolved
                }
                else { // This block is not run, why?
                    // Reject Promise and return error message to Dialogflow
                    console.log('Promise rejected');
                    var rejectMessage = 'Sorry, an error occurred.';
                    agent.add(rejectMessage);
                    reject(rejectMessage);
                }
            }) // .then end
            .catch((err) => { 
                console.log('In .catch block'); // This is run
                throw new Error('err.message from .catch: '  err.message); // This is run
            }); // .catch end
    }); // Promise end
} // searchMyData end
  

Мне неясно, как структурировать код, чтобы он выполнял отклонение обещания при возникновении ошибки. Используемая здесь структура — это то, что я видел в руководствах, с обещанием, разрешенным в блоке if и отклоненным в блоке else, все внутри .then , а затем .catch . Но мой код никогда не достигает блока else.

Или, в качестве альтернативы, можно ли вообще исключить опцию Promise rejected, или это создаст скрытые проблемы где-нибудь в будущем? Все, что я действительно хочу сделать в случае, если веб-крючок не работает, это вернуть сообщение об ошибке пользователю в Dialogflow (и зарегистрировать ошибку внутри).

Ответ №1:

Прочитайте об обещаниях. Отклоненные обещания возвращаются в качестве второго параметра в блоке then .

 rpn(options)
        .then((json) => {
            if(json) {
                // Whole bunch of code for getting the desired data 
                // and resolving the Promise
                // This part works
                var result = agent.add('Here is your data');
                resolve(result); // Promise resolved
            }
}, error => { // This block will be run on promise rejection

                console.log('Promise rejected');
                var rejectMessage = 'Sorry, an error occurred.';
                agent.add(rejectMessage);
                reject(rejectMessage);
            }
        }) // .then end
  

Комментарии:

1. Спасибо! Это помогает избавиться от «неперехваченных» сообщений об ошибках в журнале. Я все еще не получаю rejectMessage через Dialogflow, но при ближайшем рассмотрении это, похоже, связано с фиксированным временем ожидания запроса в 5 секунд для ответов webhook. Мне нужно будет найти какой-то обходной путь для этого, но, по крайней мере, теперь у меня нет неперехваченных ошибок.

2. Для продолжения я создал фиктивную версию кода, чтобы избежать тайм-аута внешнего веб-хока API, который может маскировать любые реальные проблемы. Я все еще получаю ошибку «Необработанное отклонение» в журнале, хотя приведенный выше пример избавил от «Неперехваченного исключения». Теперь мой вопрос заключается в том, стоит ли беспокоиться о необработанных отклонениях и что мне с ними делать? Я пытаюсь обработать отклонение, сгенерировав ошибку: reject(Ошибка (‘Обещание отклонено’)); но, видимо, этого недостаточно.

3. Если вы допускаете ошибку, вам нужно перехватить ее с помощью блока catch. Обещания работают хорошо, но обработку ошибок лучше всего выполнять с помощью try catch и async await . Вы можете обернуть свое обещание в блок try catch, поэтому ошибки всегда будут обрабатываться в блоке catch.

4. Еще раз спасибо! У меня есть блок catch, как в примере кода, но похоже, что просто выдача ошибки не работает. Мне также нужно будет изучить async / await. В реальном веб-крючке, если я пытаюсь смоделировать ситуацию с ошибкой, время ожидания запроса webhook просто истекает до того, как будут зарегистрированы любые другие сообщения об ошибках. Я всегда могу предоставить пользователю сообщение об ошибке через собственную консоль Dialogflow, но по-прежнему кажется, что это оставляет неразрешенное и неотраженное обещание, плавающее где-то. Хотя, может быть, облачная функция Google как-то справляется с ними за кулисами?

5. Ваш блок catch улавливает ошибку от rpn() … Но вы, должно быть, где-то вызываете searchMyData(), которая возвращает обещание. Когда это обещание (из searchMyData) отклоняется, вы его не обрабатываете. Вот почему вы видите необработанную ошибку отклонения. В общем случае блок catch должен использоваться для самой нижней функции в стеке вызовов. Это всегда будет ловить самую верхнюю ошибку, и ваша программа не столкнется с какими-либо сбоями или предупреждениями.