Как предотвратить выход Node.js во время ожидания обратного вызова?

У меня есть такой код:

var client = new mysql.Client(options);
console.log('Icanhasclient');

client.connect(function (err) {
  console.log('jannn');
  active_db = client;
  console.log(err);
  console.log('hest');

  if (callback) {
    if (err) {
      callback(err, null);
    }

    callback(null, active_db);
  }
});

Моя проблема в том, что Node завершает работу сразу же, когда я запускаю его. Он печатает 'Icanhasclient', но ни один из console.log внутри обратного вызова не вызывается.

(mysql в этом примере - это node-mysql .

Есть ли что-то, что может сделать так, чтобы node.js ждал завершения обратного вызова перед выходом?

75 голосов | спросил mikl 22 J0000006Europe/Moscow 2011, 19:43:36

5 ответов


0

Обратный вызов не поставлен в очередь

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

  emmiter1.on('this_event',callback).

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

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

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

Возможное обнаружение исправления /ошибки для пользователя - вставить специальное событие таймера перед вызовом подозрительной функции.

ответил george calvert 26 MonEurope/Moscow2011-12-26T16:59:55+04:00Europe/Moscow12bEurope/MoscowMon, 26 Dec 2011 16:59:55 +0400 2011, 16:59:55
0

Вы можете просто выполнить setTimeout или повторяющееся время ожидания с помощью setInterval.

Если вы хотите проверить условия выхода, вы также можете сделать условный тайм-аут:

(function wait () {
   if (!SOME_EXIT_CONDITION) setTimeout(wait, 1000);
})();

Поместите это в конец своего кода, и консоль будет просто ждать ... и ждать ... пока вы не захотите закрыть ее.

ответил Todd 29 AMpTue, 29 Apr 2014 05:40:20 +040040Tuesday 2014, 05:40:20
0

Мое решение состояло в том, чтобы создать экземпляр EventEmitter и прослушать мое пользовательское событие.

var eventEmitter = new process.EventEmitter();

затем я вызвал eventEmitter.emit из асинхронного обратного вызова:

client.connect(function (err) {
    eventEmitter.emit('myevent', {something: "Bla"})
});

Последним в моем сценарии было eventEmitter.on:

eventEmitter.on('myevent', function(myResult){
  // I needed the result to be written to stdout so that the calling process could get it
  process.stdout.write(JSON.stringify(myResult));
});

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

ответил you786 21 J000000Friday17 2017, 00:53:58
0

На основании ответа @ Тодда я создал однострочник. Включите его в начало вашего скрипта и установите done = true, когда вы закончите:

 var done = (function wait () { if (!done) setTimeout(wait, 1000) })();

Пример:

 var done = (function wait () { if (!done) setTimeout(wait, 1000) })();

someAsyncOperation().then(() => {
  console.log('Good to go!');
  done = true;
});

Как это работает? Если мы немного расширим его:

 // Initialize the variable `done` to `undefined`
// Create the function wait, which is available inside itself
// Note: `var` is hoisted but `let` is not so we need to use `var`
var done = (function wait () {

  // As long as it's nor marked as done, create a new event+queue
  if (!done) setTimeout(wait, 1000);

  // No return value; done will resolve to false (undefined)
})();
ответил Francisco Presencia 21 Maypm18 2018, 18:04:15
0

Я заглянул в библиотеку felixge /node-mysql и не увидел ссылки к команде client.connect в API. Это фактический звонок, который вы пытаетесь сделать (не пытаясь быть придирчивым)? Несмотря на это, IMHO, вам нужно больше думать о том, как спроектирован Javascript, потому что он использует парадигму программирования, отличную от большинства других популярных языков.

Первая проблема, которую я вижу в вашем коде, заключается в том, что вы не определили обратный вызов, поэтому он на самом деле не существует. Я бы предположил, что console.log (callback) не определен. Исходя из вашего кода, анонимная функция является «обратным вызовом» для функции client.connect. Вы должны определить, что вы называете «обратным вызовом» в более широком контексте. Например, я определю функцию myCallback, которая будет существовать в области выше, чем анонимная функция client.connect. Может быть полезно поискать Javacscript область действия переменной .

    var myCallback(err, response) {
      if (err) {
        console.log('err:%s',err);
      } else {
        console.log('response:%s',response);
      }
    }

    client.connect(err, function(response) {
      // this anonymous function is the callback to client.connect, the var
      // 'callback' would be undefined.
      if (err) {
        myCallback(err);
        return; // Explicit call to return, else the lines below would run.
      } 
      myCallback(null, response);
    });

Во-вторых, если вы не вызовете return явно в Javascript, функция продолжит обработку. Я был укушен этим сам . Наконец, Javascript запускает управляемый событиями цикл , означающий, что он никогда не будет ждать возврата функций значение, поэтому у нас есть все эти обратные вызовы в первую очередь. Вы можете заставить Javascript вести себя по-другому, например, используя цикл while, пока условие не станет истинным. Смотрите библиотеку «async» от caolan , чтобы узнать о различных стратегиях управления циклом событий. Основным недостатком чрезмерного использования этих методов является то, что вы фактически тратите циклы /блокировки ЦП, когда вам, вероятно, следует использовать больше обратных вызовов и просто переосмыслить работу своих программ.

ответил exshovelrydr 29 PMpSun, 29 Apr 2012 18:01:53 +040001Sunday 2012, 18:01:53

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132