【问题标题】:JavaScript Function should return arrayJavaScript 函数应该返回数组
【发布时间】:2016-08-15 19:19:47
【问题描述】:

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

【问题讨论】:

标签: javascript node.js function return


【解决方案1】:

您无法直接从您的函数返回值是两层问题 - 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);
}

【讨论】:

  • @M.D 如果它解决了您的问题,请您接受这个答案是正确的
【解决方案2】:

您正在混合同步和异步函数。在对 fs.readdir 进行异步调用时,您无法编写返回结果的函数。您要么需要调用同步版本 fs.readdirSync,要么不重新调整结果,而是重构您的函数,以便它获取对回调函数的引用,然后调用该函数并将结果作为参数传递。方法2是正常的Node.js做事方式。

按照您编写的方式,您的函数在 readdir 有机会执行其操作之前返回。

【讨论】:

    【解决方案3】:

    您无法返回,因为您在 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;
    }
    

    【讨论】:

      【解决方案4】:

      您不能使用 fs.readdir() 返回文件,因为它只是在文件读取完成时异步执行回调。然后文件对象本身作为参数传递给回调。

      如果要返回 readdir 的结果,有两种选择:

      1) 使用synchronous version of readdir:这将按照您的意愿返回文件系统,但是,它会阻塞节点单线程直到其完成,这可能会导致您的程序出现绝对不希望的行为, 和 f.i.在 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()... 链中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-20
        • 1970-01-01
        • 2018-04-02
        • 1970-01-01
        相关资源
        最近更新 更多