2016-08-15 60 views
1

我想从JavaScript中的文件夹中检索特定类型的文件。我正在使用正则表达式和模块'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的synchronus版本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可能是Web应用程序中的一个严重问题(每个客户端的所有请求都将被阻止,直到readdirsync完成)。

2)使用Promise。 Promise实际上不会返回像同步代码这样的值,但可以让您控制异步代码的流程,如同步代码,letting you to throw exceptions and chain return values in your code

网络,使用使用蓝鸟实现(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()首位,而其纯同步代码 - 从简单的每一个值同步代码或异步。但是,您必须将代码保存在.then()。then()...链中。