JavaScript函数应该返回数组

时间:2016-08-15 19:19:47

标签: javascript node.js function return

我正在尝试从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 //
}

4 个答案:

答案 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。