JavaScript обрабатывает асинхронные обратные вызовы узла .js - PullRequest
0 голосов
/ 07 сентября 2018

Я новичок в Javascript и только что застрял с асинхронными обратными вызовами в Javascript с использованием Node.js.

Сначала я настроил веб-крючок на Facebook и сделал POST-запрос на веб-крючок

Вот мой код: routes.js

**To set up facebook webhook**

var facebook_handler = require('../controllers/botkit').handler

module.exports = function (app) {
  // public pages=============================================
  // root
  app.get('/', function (req, res) {
    res.render('home')
  })

  app.get('/webhook', function (req, res) {
    // Check to see which webhook password (FACEBOOK_VERIFY_TOKEN) to check for, from incoming request.
    if (process.env.PORT ||process.env.VCAP_APP_PORT ) {
      FB_VERIFY_TOKEN = process.env.FACEBOOK_VERIFY_TOKEN
    } else {
      FB_VERIFY_TOKEN = process.env.FACEBOOK_VERIFY_TOKEN_DEV
    }
    // This enables subscription to the webhooks
    if (req.query['hub.mode'] === 'subscribe' && req.query['hub.verify_token'] === FB_VERIFY_TOKEN) {
      res.send(req.query['hub.challenge'])
    }
    else {
      res.send('Incorrect verify token')
    }
  })

  app.post('/webhook', function (req, res) {
    console.log("\n CALL HANDLER FUNCTION ---- \n");
    facebook_handler(req.body)
    console.log("call handler done");
    res.send('okay')
  })
}

Из вышеприведенного кода я делаю POST-запрос к Facebook webhook и получаю детали сообщения FB, а затем обрабатываю POST-запрос webhook в другом файле BotKit.js

Botkit.js

var request = require('request');
require('dotenv').load();

var handler = function (obj) {
console.log("Message received from FB \n");

  if (obj.entry ) {
    for (var e = 0; e < obj.entry.length; e++) {
           for (var m = 0; m < obj.entry[e].messaging.length; m++) {
                var facebook_message = obj.entry[e].messaging[m]
                test_message = facebook_message.message.text;
                translatorEnglish (test_message) // calling the watson translator api to get translation for the received facebook message.
     }
   }
}

Выше кода обрабатывают webhook POST-запрос и вызывают функцию Translator (перевод POST-запроса)

Функция переводчика

  var translationusername = "1234"
  var translationpassowrd = "1234"
  var transURL = "https://gateway.watsonplatform.net/language- 
  translator/api/v2/translate";

  translatorEnglish = function(test_message) {
           console.log("this should be called when translator called:" +test_message);
            var parameters = {
             text: test_message,
              model_id: 'es-en'
            };
            languageTranslator.translate(
              parameters,
              function(error, response, body) {
                if (error)
                  console.log(error)
                else
                  english_message = response.translations[0].translation
                  console.log("The response should be:" +english_message);
                  translate = false
                  //console.log(JSON.stringify(response, null, 2));
              }
            );
          };

Проблема в том, что POST-запрос перевода не выполняется до тех пор, пока обработчик вызовов не завершит POST-запрос webhook. Запрос POST на перевод всегда выполняется после завершения POST Webhook.

Есть ли способ выполнить запрос POST переводчика в запросе POST Webhook до того, как запрос POST Webhook завершится.

как то так Webhook POST -> выполнить -> Перевод POST выполнить и завершить ---> Webhook POST завершено

1 Ответ

0 голосов
/ 07 сентября 2018

Прежде всего, функция languageTranslator.translate является асинхронной функцией, поэтому она возвращает и не ждет, пока будет выполнен обратный вызов. Поэтому, если вы хотите быть уверены, что обратный вызов завершен, вы должны выполнить следующие команды после его завершения, используя новые обратные вызовы или функцию обещание .then.

Во-вторых, ваша translatorEnglish функция не имеет ни callback, ни promise. Следовательно, никто не ждет завершения вызова его асинхронной функции (languageTranslator.translate). Таким образом, Вы должны изменить его на формат обещание или формат обратного вызова (также вы можете использовать формат async await, который похож на обещание).

В-третьих, в любом случае translatorEnglish функция будет асинхронной функцией, и вы хотите использовать ее внутри цикла for в функции handle, что означает, что у вас может быть более одной асинхронной функции для ожидания, и это затрудняет ее выполнение. обрабатывается с помощью обратного вызова. Поэтому я предлагаю вам использовать обещание в этом случае, и чтобы дождаться выполнения всех обещаний, вы можете использовать Функция Promise.all .

Не забывайте, вы должны обещать все эти функции и вызывать res.send в facebook_handler().then функции.

дополнительные функции :

  • Если вы хотите преобразовать функцию с обратным вызовом в обещание без изменения ее реализации (обещание), вы можете использовать функции узла 8 util.promisify или bluebird Promise.promisify,

  • Взгляните на этот вопрос и ответ тоже.

...