2016-04-01 11 views
0

機能し、私は私のスクリプトの目的は、ディレクトリ内のPNGファイルのリストの名前を変更するノードとのECMAScript 6Promise.allはその後

を使用する方法を学ぶ呼び出すことはありません。私はpngファイルのみをリネームしたい(jpgもあるとしよう)し、最後にリネームされたファイルの数を表示したい。ノードのノンブロッキングな性質のため、それほど明白ではなく、私はES6の約束を発見する機会を利用することに決めました。

'use strict'; 

const fs = require('fs-extra'); 

const dir = '/Users/toto/Desktop/png/'; 
const suffix = '_IMAGE.'; 
const regex = /(.*)\.(png)$/; 
var nbFiles = 0; 

// Rename a png file with a suffix 
var renameFile = (filename) => { 
    return new Promise((resolve, reject) => { 
     if(regex.test(filename)){ 
     let newFileName = filename.replace(regex, '$1' + suffix + '$2'); 
     fs.rename(dir + filename, dir + newFileName, (err) => { 
      let msg = filename + ' => ' + newFileName; 

      if (err) { 
      console.log('KO : rename of ' + msg); 
      reject(err); 
      } 

      console.log('OK : rename of ' + msg); 
      resolve(nbFiles++); 
     }); 
     } 
    }); 
}; 

// Read files in a directory and call renameFile + display number of files renamed 
fs.readdir(dir, (err, files) => { 
    if(err) return console.error(err); 

    var promise = Promise.all(
     files.map(renameFile) 
    ).then(function(nb){ 
     console.log('Number of files renamed : ', nb); 
    }).catch(function(err){ 
     console.log('Error ', err); 
    }); 
}); 

期待される結果は、名前が変更されたファイルを取得すると、名前が変更されたファイルのメッセージ数を確認することです。

ファイルの名前が変更されましたが、(その時またはキャッチコールの)メッセージは表示されません。どこかに何か間違っていますが、デバッグセッションは私を助けません。

ありがとうございました!

PS:私の環境はノード5.10とOS X 10.11です。

+0

あなたは本当に最低限のレベルでpromisfyする必要があります - 'fs.rename'の約束だけを作成し、それ以外は何もありません。ロジックもログもありません。あなたの問題は、 'regex'がマッチしないときにあなたの約束が決して解決されないということです。 – Bergi

答えて

2

問題は、regexfilenameと一致しない場合、永久に保留されている(決して解決されない)いくつかの約束を作成しているということです。 Promise.allは無期限にそれらを待ちます。あなたのケースfs.renamefs.readdirで - -

あなたはいつもpromisify可能な限り低いレベルにすべきであり、「古い」のコールバックAPIを扱うその関数の内部では他のコードを入れていません。アプリケーションロジックなし、文字列連結なし、ロギングなし、何もありません。

function rename(from, to) { 
    return new Promise((resolve, reject) => { 
     fs.rename(from, to, (err, res) => { 
      if (err) reject(err); 
      else resolve(res); 
     }); 
    }); 
} 
function readdir(from, to) { 
    return new Promise((resolve, reject) => { 
     fs.readdir(from, to, (err, res) => { 
      if (err) reject(err); 
      else resolve(res); 
     }); 
    }); 
} 

(それが反復思われる場合 - それはさ - ヘルパー関数を記述し、または約束ライブラリからいずれかを使用する)ものと

を、あなたは正しく(と簡単に)あなたのスクリプトを実装できます。

const dir = '/Users/toto/Desktop/png/'; 
const suffix = '_IMAGE.'; 
const regex = /(.*)\.(png)$/; 
readdir(dir).then(files => 
    Promise.all(files.map(filename => ({ 
     from: dir + filename, 
     to: dir + filename.replace(regex, '$1' + suffix + '$2') 
    })).filter(r => r.from != r.to).map(r => { 
     let msg = r.from + " => " + r.to; 
     return rename(r.from, r.to).then(() => { 
      console.log("OK: " + msg); 
     }, err => { 
      console.log("KO: " + msg); 
      throw err; 
     }); 
    })); 
).then(function(res) { 
    console.log('Number of files renamed : ', res.length); 
}).catch(function(err) { 
    console.error('Error ', err); 
}); 
+0

興味深いコード!私はまた、正規表現の第1のテストとsthの第2のテストの命令的パターンを避けるということも好きです。代わりに、 "自分自身に名前を変更"されるファイルを除外します。 –

+0

これは本当に良いコードで、何が起こっているのかがはるかに簡単です。 – Wainage

+0

あなたの素早く優雅な答えに感謝のBergi! 私はそれが最も低いレベルで約束する方が良いことを理解します。私の関数renameFileは多くのことをしました(regex test + rename)。 匿名のオブジェクト(fromとtoのプロパティを持つ)を導入して、後でそれを関数的に使う方法が大好きです。私はfunctionnalはまだ十分だとは思わない。 return renamの後に.catch()がコードにないと思います。あなたは将来の人々のために@Bergiを編集できますか? – pom421