почему я не определен в этой функции?

#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. Я рад, что это помогло! Я просто делаю то немногое, что могу, чтобы помочь людям и отблагодарить многих людей, которые помогли (и все еще помогают!) Мне.