#javascript #promise #dialogflow-es #dialogflow-es-fulfillment #airtable
#javascript #обещание #dialogflow-ы #dialogflow-es-выполнение #airtable
Вопрос:
Я создаю агент dialogflow, который использует Airtable в качестве базы данных (библиотека: airtable js)
Все работает нормально, за исключением того, что я не могу получить значение «из» функции, чтобы отправить его обратно агенту dialogflow.
Функция
function showSinglePrice(agent) {
var finalPrice;
var arraySinglePrice = null;
const item = agent.context.get("item"),
place = item.parameters.place,
size = item.parameters.size,
type = item.parameters.type;
base(tablePlaces)
.select({
maxRecords: 10,
view: viewName,
filterByFormula: `AND({type} = "${type}",{size} = "${size}",{place} = "${place}")`
})
.firstPage(function(error, records) {
if (error) {
response.send({ error: error });
} else {
arraySinglePrice = records.map(record => {
return {
price: record.get("price")
};
});
console.log(arraySinglePrice); //this works fine
finalPrice = arraySinglePrice[0].price; //this works fine
return finalPrice;
}
});
agent.add(`I wanted to get the result in here: ${finalPrice}`); //undefined
}
Я новичок в асинхронном программировании, поэтому я, вероятно, путаюсь с обещаниями Airtable js, но не могу понять, как заставить его работать.
Был бы признателен за любую помощь
Редактировать
СПАСИБО @PRISONER ЗА ПОМОЩЬ.
ДЛЯ ТЕХ, КТО НУЖДАЕТСЯ, ВОТ РАБОЧИЙ КОД:
function showSinglePrice(agent) {
const item = agent.context.get("item"),
place = item.parameters.place,
size = item.parameters.size,
type = item.parameters.type;
return base(tablePlaces) //defined variable before this function
.select({
maxRecords: 1, //just want 1
view: viewName, //defined variable before this function
filterByFormula: `AND({type} = "${type}",{size} = "${size}",{place} = "${place}")`
})
.firstPage()
.then(result => {
console.log(result);
var getPrice = result[0].fields.price;
agent.add(`the current price is: $ ${getPrice}`); //its working
})
.catch(error => {
console.log(error);
response.json({
fulfillmentMessages: [
{
text: {
text: ["We got the following error..."] //will work on it
}
}
]
});
});
}
Комментарии:
1. Переместите обратный вызов
agent.add()
внутриfirstPage
и заменитеreturn
им,return finalPrice
которому некуда возвращаться, и вы вызываете add() до завершения всей цепочки выбора2. Спасибо, Чарли. Если я это сделаю, я получу следующую ошибку: UnhandledPromiseRejectionWarning: Ошибка: нет ответов, определенных для платформы: null в V2Agent.sendResponses_ (/rbd/pnpm-volume/54a37ce2-dee9-4e33-af7f-21d280ce7234/node_modules/.registry.npmjs.org/dialogflow-fulfillment/0.6.1/node_modules/dialogflow-fulfillment/src/v2-agent.js:243:13 ) Предупреждение о необработанном PROMISEREJECTIONWARNING: отклонение необработанного обещания. Эта ошибка возникла либо из-за ввода внутри асинхронной функции без блока catch, либо из-за отклонения обещания, которое не было обработано с помощью .catch().
Ответ №1:
Вы правы, есть некоторые проблемы с тем, как вы используете Promises. Вы используете функцию обратного вызова в своем вызове firstPage()
вместо того, чтобы возвращать обещание. Итак, вы могли бы написать эту часть, чтобы она выглядела примерно так:
.firstPage()
.then( records => {
// Work with the records here
})
.catch( err => {
// Deal with the error
});
Как только вы имеете дело с Promises, все, что вы хотите сделать, должно выполняться внутри .then()
блока. Итак, вам нужно переместить agent.add()
туда.
Вам также нужно вернуть обещание, чтобы Dialogflow знал, что выполняется асинхронная операция. Поскольку функции .then()
и .catch()
возвращают обещание, вы можете просто вернуть результат всего выражения. Итак, что-то вроде
return base(tablePlaces)
.select(query)
.firstPage()
.then(/*function*/)
.catch(/*function*/);
Комментарии:
1. вы не устаете спасать жизни людей? 😀 Я боролся с этим 3 дня .. tks!
2. Я рад, что это помогло! Я просто делаю то немногое, что могу, чтобы помочь людям и отблагодарить многих людей, которые помогли (и все еще помогают!) Мне.