2016-08-15 4 views
1

Я пытаюсь получить определенный тип файлов из папки в JavaScript. Я использую Regex и модуль 'fs' для этого. Функция, которую я пытаюсь создать, не возвращает ничего. Я могу увидеть массив после его печати, но я не могу его вернуть. Я хочу, чтобы функция возвращала массив имен этих конкретных файлов. Вот кодФункция JavaScript должна возвращать массив

var fs = require('fs'); 
var dir = '/../../'; 
var ext = 'yml'; 
function test1() { 
    var c = new Array(); 
    fs.readdir(dir, function (err, list) { 
    var re = new RegExp("^.*\." + ext + "$"); 
    list.forEach(function(item) { 
    if(re.test(item)) { 
     c.push(item); 
    } 

    // return item; 
    }); 

    console.log(c) 

    }); 
    // return c // 
} 
+1

Если вы хотите вернуть массив, вы, вероятно, ищете версию синхронного чтения readdir https://nodejs.org/api/fs.html#fs_fs_readdirsync_path_options –

+0

Почему вы хотите вернуть элемент из readdir? Это нигде не попадает – Jay

ответ

3

Вы два слоя в глубине не в состоянии возвратить значение непосредственно из вашей функции - readdir асинхронные и forEach не возвращают значения из прилагаемого обратного вызова. Попробуйте использовать readdirSync и используйте filter для удаления несоответствующих файлов.

function test1() { 
    var files = fs.readdirSync(dir); 
    return files.filter(function(item) { 
     return re.test(item); 
    }); 
} 

Или более succintly:

function test1() { 
    return fs.readdirSync(dir).filter(re.test); 
} 
+1

@M.D Не могли бы вы принять этот ответ правильно, если он исправил вашу проблему – Jay

0

Вы не можете вернуться, потому что ты внутри forEach функции. Вот решение, использующее цикл for, который вы действительно можете вернуть с

var fs = require('fs'); 
var dir = '/../../'; 
var ext = 'yml'; 
function test1() { 
    var c = new Array(); 
    var tmp = null; 
    fs.readdirSync(dir, function(err, list) { 
    var re = new RegExp("^.*\." + ext + "$"); 
    for(var i = 0; i < list.length; i++) { 
     var item = list[i]; 
     // in your example, if doesn't have any {}. This is bad. 
     if(re.test(item)) { 
      c.push(item); 
      // not sure why you said you wanted to return item here 
      // but you're inside of another function so you can't. 
      // Only way to do so is to set it equal to a variable 
      // this function has closed around. 
      // tmp = item; 
     } 
     }); 

    console.log(c) 
    }); 
    return c; 
} 
1

Вы смешиваете синхронные и асинхронные функции. Вы не можете написать функцию, которая возвращает результат, вы делаете асинхронный вызов fs.readdir. Вам либо нужно позвонить в синхронную версию fs.readdirSync, либо вместо того, чтобы перенастроить результат, восстановите свою функцию, чтобы она ссылалась на функцию обратного вызова, а затем вызывает эту функцию и передает результат в качестве параметра. Метод 2 является обычным способом Node.js делать вещи.

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

0

Вы не можете вернуть файл, используя fs.readdir(), поскольку он просто выполняет обратный вызов асинхронно, когда чтение файла выполняется. Затем сам объект файла передается на обратный вызов в качестве параметра.

Если вы хотите, чтобы вернуть результат ReadDir, у вас есть два варианта:

1) Используйте synchronous version of readdir: это вернет файловую систему, как вы хотите, однако, он блокирует узел одного потока до его сделано, и это может привести к совершенно нежелательному поведению в вашей программе, и fi может быть серьезной проблемой в веб-приложении (все запросы от каждого клиента будут заблокированы до тех пор, пока не будет выполнено чтениеdirynync).

2) Используйте Promise. Promise фактически не возвращает такие значения, как синхронный код, но позволяет вам контролировать поток вашего асинхронного кода, как если бы он был синхронным, letting you to throw exceptions and chain return values in your code.

Fi, пример использования посылов с помощью Bluebird реализации (which requires to install the bluebird package):

var fs = require('fs'); 
var Promise = require('bluebird'); 
var dir = '/../../'; 
var ext = 'yml'; 
var readdirAsync = Promise.promisify(fs.readdir); 
//var c = new Array(); You dont need c as a global now, since you can return the result of the function from inside the iterateOverDir function. 

/*Now this function returns a Promise that will pass the readdir value when the promise is fullfilled*/ 
var test1 = function() { 
    /*yeah a single line function is pretty redundant but is to keep consistence with the OP code*/ 
    return fs.readdirAsync(dir); 
} 
/* 
and this function just iterates over list performing some actions and 
returning a 'result' array. When this whole function is passed as a parameter in a .then(), it takes whatever the function inside the previous then/promise returns, and pass its return value to the next. This is true whenever the previous promise/then is synchronous or asynchronous code. 
*/ 
var iterateOverDir = function(list){ 
    var re = new RegExp("^.*\." + ext + "$"); 
    list.forEach(function(item) { 
    var result = new Array(); 
    if(re.test(item)) { 
    result.push(item); 
    } 
    return result; 
} 
test1.then(iterateOverDir).catch(console.log) 
then(console.log /* or whatever function that uses the previous function return value.*/); 

Теперь, благодаря обетованному, вы можете трубы к iterateOverDir() -Какие ведают Синхронные code- каждое значение от простого синхронный код или асинхронный. Однако вы должны сохранить свой код внутри цепочек .then(), then() ....

Смежные вопросы