Управление большой рекурсией обратного вызова в Nodejs

Я был заинтригован так, я искал его в определении редактор ECMAScript 262 3 , который является основанием JavaScript 1.8. Соответствующее определение найдено в разделе 11.1.4 и к сожалению не очень четкое. Раздел явно указывает, что elisions (= пропуск) вначале или в середине не определяют элемент , но действительно способствуют полной длине .

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

соответствующий абзац читает следующим образом:

Элементы массива могут игнорироваться вначале, середина или конец списка элемента. Каждый раз, когда запятой в списке элемента не предшествует Выражение присваивания (т.е. запятая вначале или после другой запятой), недостающий элемент массива способствует длине Массива и увеличивает индекс последующих элементов. Игнорируемые элементы массива не определяются.

18
задан Jonas 27 April 2010 в 23:35
поделиться

6 ответов

Ни один из показываемых вами кодов не использует рекурсию. Когда вы вызываете useFile , он вызывает posix.stat () , который возвращает, а useFile завершает свою работу по мере выполнения. Некоторое время спустя, когда вызов posix.stat () завершится в базовой системе и будут доступны результаты, функция обратного вызова, которую вы добавили для этого, будет выполнена. Это вызывает posix.open () , а затем завершается по мере выполнения. Как только файл был успешно открыт, функция обратного вызова для , которую выполнит, вызовет posix.read () , а затем завершит свою работу, так как она тоже завершилась. Наконец, когда станут доступны результаты чтения, будет выполнена самая внутренняя функция.

Важным моментом является то, что каждая функция выполняется до завершения, поскольку вызовы функций posix. * () являются неблокирующими: то есть они возвращаются немедленно, вызывая запуск некоторой магии. выключен в базовой системе. Таким образом, каждая из ваших функций завершается, и позже событие вызовет выполнение следующей функции; но никакой рекурсии там нет.

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

РЕДАКТИРОВАТЬ: Попробуйте добавить несколько операторов регистрации непосредственно перед концом каждой вложенной функции;

24
ответ дан 30 November 2019 в 07:50
поделиться

Как и в любом JavaScript, с помощью Node.js. можно выполнять рекурсивные вызовы. Если вы столкнетесь с проблемами глубины рекурсии (как указывает NickFitz, вам, похоже, это не грозит), вы можете часто переписывать свой код, чтобы вместо этого использовать интервальный таймер.

0
ответ дан 30 November 2019 в 07:50
поделиться

Your stuff is fine. I do recursive calls in Express to follow HTTP redirects, but what your doing is "traversal" and not recursion

1
ответ дан 30 November 2019 в 07:50
поделиться

Один пример, с отладочной продукцией Добавлено (см. Ниже для вывода):

UseFile.js:

var sys = require("sys"),
  posix = require("posix");

var useFile = function(filename,callback){
    posix.stat(filename).addCallback(function (stats) {
        posix.open(filename, process.O_RDONLY, 0666).addCallback(function (fd) {
            posix.read(fd, stats.size, 0).addCallback(function(contents){
                callback(contents);
                sys.debug("useFile callback returned");
            });
            sys.debug("read returned");
        });
        sys.debug("open returned");
    });
    sys.debug("stat returned");
};

useFile("usefile.js",function(){});

Выход:

DEBUG: stat returned
DEBUG: open returned
DEBUG: read returned
DEBUG: useFile callback returned
3
ответ дан 30 November 2019 в 07:50
поделиться

Вы можете попробовать

http://github.com/creationix/do

или сделать свой собственный, как это сделал я. Не обращайте пока внимания на отсутствие обработки ошибок (просто игнорируйте это) ;)

var sys = require('sys');

var Simplifier = exports.Simplifier = function() {}

Simplifier.prototype.execute = function(context, functions, finalFunction) {
  this.functions = functions;
  this.results = {};
  this.finalFunction = finalFunction;
  this.totalNumberOfCallbacks = 0
  this.context = context;
  var self = this;

  functions.forEach(function(f) {
    f(function() {
      self.totalNumberOfCallbacks = self.totalNumberOfCallbacks + 1;
      self.results[f] = Array.prototype.slice.call(arguments, 0);     
      if(self.totalNumberOfCallbacks >= self.functions.length) {
        // Order the results by the calling order of the functions
        var finalResults = [];
        self.functions.forEach(function(f) {
          finalResults.push(self.results[f][0]);
        })
        // Call the final function passing back all the collected results in the right order 
        finalFunction.apply(self.context, finalResults);
      }
    });
  });
}

И простой пример с его использованием

// Execute 
new simplifier.Simplifier().execute(
  // Context of execution
  self,  
  // Array of processes to execute before doing final handling
  [function(callback) {
      db.collection('githubusers', function(err, collection) {
        collection.find({}, {limit:30}, function(err, cursor) {
          cursor.toArray(function(err, users) { callback(users); })
        });
      });      
    },

    function(callback) {
      db.collection('githubprojects', function(err, collection) {
        collection.find({}, {limit:45, sort:[['watchers', -1]]}, function(err, cursor) {
          cursor.toArray(function(err, projects) { callback(projects); })
        });
      });              
    }
  ],  
  // Handle the final result
  function(users, projects) {
    // Do something when ready
  }
);
3
ответ дан 30 November 2019 в 07:50
поделиться

Также обратите внимание на 'step' ( http://github.com/creationix/step ) или 'flow-js' на гитхабе. Это позволяет вам писать потоки обратного вызова в более естественном стиле. Это также даст понять, что рекурсии не происходит.

1
ответ дан 30 November 2019 в 07:50
поделиться
Другие вопросы по тегам:

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