JavaScript函数应该返回数组
我正尝试从JavaScript中的文件夹中检索特定types的文件。 我正在使用正则expression式和模块'fs'。 我试图构build的函数不返回任何东西。我可以看到数组一旦我打印它,但我不能够返回它。 我想要的是该函数应该返回这些特定文件的名称数组。 这是代码
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 // }
你不能直接从你的函数返回一个值 – readdir
是asynchronous的, forEach
不会从所提供的callback中返回值。 尝试使用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); }
您正在混合同步和asynchronousfunction。 你不能写一个函数,在你对fs.readdir进行asynchronous调用时返回一个结果。 您可能需要调用同步版本fs.readdirSync,或者不重新调用结果,而是重新构build函数,以便引用callback函数,然后调用该函数并将结果作为parameter passing。 方法2是正常的Node.js处事方式。
你写的方式,你的函数在readdir有机会做它的事情之前返回。
你不能返回,因为你在一个forEach
函数。 以下是使用for循环的解决scheme,您可以从中返回
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; }
您不能使用fs.readdir()来返回文件,因为它只是在文件读取完成时才asynchronous执行callback。 然后,文件对象本身作为parameter passing给callback函数。
如果你想返回readdir的结果,你有两个select:
1)使用readdir的同步版本 :这将会按照你的意愿返回文件系统,但是它会阻塞节点单线程,直到完成 ,这会导致程序中绝对不受欢迎的行为,而fi可能是一个严重的问题。一个Web应用程序(每个客户端的所有请求将被阻止,直到readdirsync完成)。
2)使用承诺 。 Promise实际上并不像同步代码那样返回值,而是允许你像asynchronous代码一样控制asynchronous代码的stream, 让你在代码中抛出exception和链返回值 。
Fi,使用Bluebird实现( 需要安装bluebird软件包 )使用Promises的示例:
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.*/);
现在,由于承诺,你可以pipe道iterateOverDir() – 这是普通的同步代码 – 每个值从普通的同步代码或asynchronous。 但是,您必须将您的代码保存在.then()。then()…链中。