我正在尝试从JavaScript中的文件夹中检索特定类型的文件。我正在使用正则表达式和模块' fs'为了它。 我正在尝试构建的函数不会返回任何内容。我可以在打印数据后看到该数组,但我无法返回它。我想要的是该函数应该返回这些特定文件的名称数组。 这是代码
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 //
}
答案 0 :(得分:3)
您无法直接从函数返回值,因此只有两层 - readdir
是异步的,forEach
不会从提供的回调中返回值。请尝试使用readdirSync并使用filter
删除不匹配的文件。
function test1() {
var files = fs.readdirSync(dir);
return files.filter(function(item) {
return re.test(item);
});
}
或者更加简洁:
function test1() {
return fs.readdirSync(dir).filter(re.test);
}
答案 1 :(得分:1)
您正在混合同步和异步功能。在编写fs.readdir异步调用时,您无法编写返回结果的函数。您需要调用同步版本fs.readdirSync,或者重新调整结果,而不是重新调整结果,因此它会引用回调函数,然后调用该函数并将结果作为参数传递。方法2是正常的Node.js服务方式。
你编写它的方式,你的函数在readdir有机会做之前就会返回。
答案 2 :(得分: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;
}
答案 3 :(得分: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一样。
F.i。,使用Bluebird实现使用Promises的示例(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.*/);
现在,感谢Promise,你可以管道到iterateOverDir() - 这是普通的同步代码 - 来自普通同步代码或异步的每个值。但是,您必须将代码保存在.then()。then()... chains。
中