Инициировать выполнение webhook асинхронно из намерения?

У меня есть некоторые намерения, которые должны вызвать выполнение webhook и не заботятся о ответе. Для ответа веб-крючка требуется больше времени, чем для тайм-аута, поэтому я хотел бы, чтобы намерение было просто ответить "Спасибо за беседу", а затем закрыть разговор, фактически запуская веб-крючок.

Чувствует себя легко, но я что-то упускаю. Также я новичок в диалоге вещей.

Я могу сделать это на любом языке, но вот пример в Javascript:

fdk.handle(function (input) {
  // Some code here that takes 20 seconds.

  return {'fulfillmentText': 'i can respond but I will never make it here.'}
});

РЕДАКТИРОВАТЬ 1 - Попытка асинхронного

Когда я использую асинхронную функцию, запрос POST никогда не происходит. Итак, в следующем коде:

fdk.handle(function (input) {
  callFlow(input);
  return { 'fulfillmentText': 'here is the response from the webhook!!' }
});

async function callFlow(input) {
  console.log("input is --> " + input)

  var url = "some_url"

  console.log("Requesting " + url)

  request(url, { json: true, headers: {'Access-Control-Allow-Origin' : '*'} }, (err, res, body) => {
    if (err) { return console.log(err); }
    console.log("body is...")
    console.log(body)
  });
}

Я вижу в логах два выхода console.log, но ничего из запроса. И, похоже, запрос тоже не происходит, потому что я не вижу его в своей конечной точке.

РЕШЕНИЕ

Спасибо Заключенному за подсказку. Похоже, мне нужно было вернуть выполнение JSON обратно через функции callFlow() и handle(). Теперь у Google Home нет времени ожидания, и генерируются как HTTP-вызов, так и ответ.

const fdk = require('@fnproject/fdk');
const request = require('request');

fdk.handle(function (input) {
  return callFlow(input);
});

async function callFlow(input) {
  var searchPhrase = input || "cats"
  var url = "some url"

  return new Promise((resolve, reject) => {
    request.post(url, {
      headers: { 'content-type': 'application/x-www-form-urlencoded' },
      body: searchPhrase
    },
      function (err, resp, body) {
        if (err) { return console.log(err) }
        r = { 'fulfillmentText': `OK I've triggered the flow function with search term ${searchPhrase}` }
        resolve(r)
      }
    );
  });

}

1 ответ

Решение

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

Однако вы можете выполнить асинхронную операцию в выполнении, которая не завершится, прежде чем вы вернете результат.

Если вы используете достаточно современную версию узла (версия 8 и выше), вы можете сделать это, объявив функцию как async функция, но не вызывая его с await ключевое слово. (Если вы позвонили с await, он будет ждать завершения асинхронной операции, прежде чем продолжить.)

Так что примерно так должно работать, учитывая ваш пример:

async function doSomethingLong(){
  // This takes 20 seconds
}

fdk.handle(function (input) {
  doSomethingLong();

  return {'fulfillmentText': 'This might respond before doSomethingLong finishes.'}
});

Обновите 1 на основе вашего примера кода.

Кажется странным, что вы сообщаете, что звонок request кажется, не сделано вообще, но есть некоторые странные вещи, которые могут быть причиной этого.

Первый, request сама по себе не является асинхронной функцией. Он использует модель обратного вызова и async функции не просто автоматически ждут, когда будут вызваны эти обратные вызовы. Так что ваши callFlow() вызовы функций console.log() пару раз звонит request() и возвращает до обратного вызова.

Вы, вероятно, должны заменить request с чем-то вроде пакета request-обещание-native и ждите обещание, которое вы получите от звонка. Это делает callFlow() действительно асинхронный (и вы можете войти, когда он заканчивает вызов).

Во-вторых, я хотел бы отметить, что код, который вы показали, не выполняет операцию POST. Это делает GET по умолчанию. Если вы или API, который вы вызываете, ожидаете POST, это может быть источником ошибки. Тем не менее, я бы ожидал err параметр для заполнения, и ваш код выглядит так, как будто он проверяет и регистрирует это.

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

Другие вопросы по тегам