2016-08-15 81 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()...鏈中。