#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 должен использоваться для самой нижней функции в стеке вызовов. Это всегда будет ловить самую верхнюю ошибку, и ваша программа не столкнется с какими-либо сбоями или предупреждениями.