2014-12-29 3 views
0

У меня есть приложение NodeJS, которое использует API fs для чтения файлов из дерева каталогов. Я использую модуль fs-walk, чтобы ходить по дереву. Для каждого найденного подкаталога эта же функция снова выполняет его обработку. (Я не думаю, что это рекурсия, скорее, одна и та же функция привязана к событию, которое запускается каждый раз, когда обрабатывается каталог.) Файлы обрабатываются с помощью другой функции, которая делает вещи для них.NodeJS fs API: обнаружение асинхронного завершения

Я хотел бы выполнить произвольный код, как только все файлы были прочитаны без использования синхронного или блокирующего кода. Я не мог найти способ отслеживать количество файлов в каталоге (например, для обратного отсчета), а также не мог найти какой-либо атрибут в fs.stat, чтобы указать, что вся операция завершена.

Если бы кто-нибудь нашел способ сделать это еще? Я не мог найти ничего в документах узлов или переполнении стека.

+0

Я сделал это в моем модуле: https://github.com/micnic/simpleS/blob/master/lib/cache.js, проверить его, он проходит через дерево каталогов, кэшировать каталоги и файлы, сохранить их статистику и следить за изменениями – micnic

ответ

0

После рассмотрения библиотеки fs-walk немного ближе, похоже, что третий аргумент метода walk() на самом деле является final callback. Внутри они используют библиотеку async, в частности async.whilst() и async.waterfall() методы, которые будут выполнять окончательный обратный вызов, когда все будет завершено.

Я думаю, что намерение создателя библиотеки заключается в том, что этот окончательный ответ будет выполнен, когда все асинхронные действия будут завершены. Если это не работает, вы можете file an issue in Github для него:

Согласно кодексу, вы должны быть в состоянии сделать:

var walk = require('fs-walk'; 

walk('/some/dir', someFileOrDirHandler, function(err) { 
    // This should be a final callback, if the first argument is present, 
    // then there was an error 
    if (err) { 
     /* handle it */ 
     return; 
    } 

    // Getting here indicates success 
}); 
+0

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

+0

Ах, но можете ли вы передать массив каталогов в метод 'walk()' в качестве первого аргумента? Решает ли ваша проблема? – jakerella

+0

К сожалению, нет, так как есть x вложенных каталогов. Почему API-интерфейс nodejs 'fs не дает количество «детей» для любого данного каталога, является неудачным :( –

0

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

var countAllFiles = new Promise(function (resolve, reject) { 
    var total = 0, 
    count = function (path) { 
     var contents = fs.readdirSync(path), file, name; 
     for (file in contents) { 
      if (!contents.hasOwnProperty(file)) continue; 
      name = path + '/' + contents[file]; 
      if (fs.statSync(name).isDirectory()) 
       count(name); 
      else 
       ++total; 
     } 
    }; 
    count('/path/to/tree/'); 
    resolve(total); 
}).then(function (total) { 
    walk.dirs('/path/to/tree/', handlerFunction, errorHandler); 
    // for every file, decrement total. Then, if it's zero, execute the code that 
    // depends on all the read/write operations being complete 
}); 
Смежные вопросы