2016-08-15 17 views
1

JavaScriptのフォルダから特定の種類のファイルを取得しようとしています。私はRegexとモジュール 'fs'を使っています。 ビルドしようとしている関数は何も返しません。一度印刷すれば配列を見ることができますが、返すことはできません。私が望むのは、関数がそれらの特定のファイルの名前の配列を返す必要があるということです。 readdirが供給コールバックから値を返さない非同期であり、forEach - は、ここでは深くあなたの関数から直接値を返すことができないで2つの層がある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

コードです。代わりに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の結果を返したい場合は、次の2つのオプションがあります。

1)synchronous version of readdirを使用します。これはそのまでノードつのスレッドをあなたが望むように、しかし、ファイルシステムを返すてブロックしますが完了し、これがプログラム上で絶対に望ましくない動作を引き起こす可能性があり、fi Webアプリケーションで深刻な問題になる可能性があります(すべてのクライアントからのすべての要求は、readdirsyncが完了するまでブロックされます)。

2)Promiseを使用してください。プロミスは実際には同期コードのような値を返すわけではありませんが、同期のように非同期コードのフローを制御することができますletting you to throw exceptions and chain return values in your code

Fiが、ブルーバード実装(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(へのパイプをすることができます)、プレーンからすべての値平野同期コード - ある-which同期コードまたは非同期です。しかし、コードを.then()。then()...チェーンの中に入れておく必要があります。

関連する問題