死のピラミッドを水平にする方法

マニュアルに従ってwebpackを設定するには、角度をプログラムし、さらにajax経由でjsonを送信します。誰でもできるように思えますが、コード自体を見る方法は次のとおりです。この投稿では、イノベーションの違いを示します。



そのため、ノードを開いて、ほとんどすべての関数が「そのまま」最後の引数としてコールバックを受け入れることがわかりました。



var fs = require("fs"); fs.readdir(__dirname, function(error, files) { if (error) { console.error(error); } else { for (var i = 0, j = files.length; i < j; i++) { console.log(files[i]); } } });
      
      







死のピラミッド





そして実際に問題は何ですか? 問題は、網膜を備えたポピーでは、スペースのスペースが終わることがあり(もちろん、タブ上の4つのスペースが贅沢だと言うことができます)、そのような関数を少なくとも1ダース以上使用すると、コード全体がずっと右に見えます。







 var fs = require("fs"); var path = require("path"); var buffers = []; fs.readdir(__dirname, function(error1, files) { if (error1) { console.error(error1); } else { for (var i = 0, j = files.length; i < j; i++) { var file = path.join(__dirname, files[i]); fs.stat(file, function(error2, stats) { if (error2) { console.error(error2); } else if (stats.isFile()) { fs.readFile(file, function(error3, buffer) { if (error3) { console.error(error3); } else { buffers.push(buffer); } }); } }); } } }); console.log(buffers);
      
      







それで、これで何ができるのでしょうか? ライブラリを使用しない場合、明確にするために、すべての例でコードの行を使用しないため、sugar es6およびes7を使用してこれを処理する方法を後で示します。



約束



組み込みオブジェクトを使用すると、ピラミッドをわずかに平坦化できます。



 var fs = require("fs"); var path = require("path"); function promisify(func, args) { return new Promise(function(resolve, reject) { func.apply(null, [].concat(args, function(error, result) { if (error) { reject(error); } else { resolve(result); } })); }); } promisify(fs.readdir, [__dirname]) .then(function(items) { return Promise.all(items.map(function(item) { var file = path.join(__dirname, item); return promisify(fs.stat, [file]) .then(function(stat) { if (stat.isFile()) { return promisify(fs.readFile, [file]); } else { throw new Error("Not a file!"); } }) .catch(function(error) { console.error(error); }); })); }) .then(function(buffers) { return buffers.filter(function(buffer) { return buffer; }); }) .then(function(buffers) { console.log(buffers); }) .catch(function(error) { console.error(error); });
      
      







コードはもう少しなりましたが、エラー処理は大幅に削減されました。



Promise.allはフェイルファースト戦略を使用し、実際に少なくとも1つのプロミスによってスローされた場合、エラーをスローするため、.catchが2回使用されていることに注意してください。 、そして最初の「死者」で途切れない。 この問題はQおよびBluebirdライブラリなどによって解決されているため、カバーしません。



次に、すべてを矢印関数、記述的割り当て、およびモジュールで書き換えます。



 import fs from "fs"; import path from "path"; function promisify(func, args) { return new Promise((resolve, reject) => { func.apply(null, [...args, (err, result) => { if (err) { reject(err); } else { resolve(result); } }]); }); } promisify(fs.readdir, [__dirname]) .then(items => Promise.all(items.map(item => { const file = path.join(__dirname, item); return promisify(fs.stat, [file]) .then(stat => { if (stat.isFile()) { return promisify(fs.readFile, [file]); } else { throw new Error("Not a file!"); } }) .catch(console.error); }))) .then(buffers => buffers.filter(e => e)) .then(console.log) .catch(console.error);
      
      







発電機



今では非常に優れていますが、結局、新しいタイプの関数*とキーワードyeildを追加するジェネレーターがいくつかあります。これらを使用するとどうなりますか?



 import fs from "fs"; import path from "path"; function promisify(func, args) { return new Promise((resolve, reject) => { func.apply(null, [...args, (err, result) => { if (err) { reject(err); } else { resolve(result); } }]); }); } function getItems() { return promisify(fs.readdir, [__dirname]); } function checkItems(items) { return Promise.all(items.map(file => promisify(fs.stat, [path.join(__dirname, file)]) .then(stat => { if (stat.isFile()) { return file; } else { throw new Error("Not a file!"); } }) .catch(console.error))) .then(files => { return files.filter(file => file); }); } function readFiles(files) { return Promise.all(files.map(file => { return promisify(fs.readFile, [file]); })); } function * main() { return yield readFiles(yield checkItems(yield getItems())); } const generator = main(); generator.next().value.then(items => { return generator.next(items).value.then(files => { return generator.next(files).value.then(buffers => { console.log(buffers); }); }); });
      
      







generator.next()。Value.thenからのチェーンは、最初の例のコールバックよりも優れているわけではありませんが、これはジェネレーターが不良であることを意味するものではなく、このタスクに適合しません。



非同期/待機



泥だらけのキーワードがもう2つあります。これは、ファイルの読み取りタスクに既に煩わされているソリューションに固執しようとすることを意味します-Async / Await
 import fs from "fs"; import path from "path"; function promisify(func, args) { return new Promise((resolve, reject) => { func.apply(null, [...args, (error, result) => { if (error) { reject(error); } else { resolve(result); } }]); }); } function getItems() { return promisify(fs.readdir, [__dirname]); } function checkItems(items) { return Promise.all(items.map(file => promisify(fs.stat, [path.join(__dirname, file)]) .then(stat => { if (stat.isFile()) { return file; } else { throw new Error("Not a file!"); } }) .catch(console.error))) .then(files => { return files.filter(file => file); }); } function readFiles(files) { return Promise.all(files.map(file => { return promisify(fs.readFile, [file]); })); } async function main() { return await readFiles(await checkItems(await getItems())); } main() .then(console.log) .catch(console.error);
      
      







おそらく最も美しい例は、すべての機能が仕事で忙しく、ピラミッドがないことです。



たとえば、このコードを書くことが次のようになっていない場合、次のようになります。



 import bluebird from "bluebird"; import fs from "fs"; import path from "path"; const myFs = bluebird.promisifyAll(fs); function getItems(dirname) { return myFs.readdirAsync(dirname) .then(items => items.map(item => path.join(dirname, item))); } function getFulfilledValues(results) { return results .filter(result => result.isFulfilled()) .map(result => result.value()); } function checkItems(items) { return bluebird.settle(items.map(item => myFs.statAsync(item) .then(stat => { if (stat.isFile()) { return [item]; } else if (stat.isDirectory()) { return getItems(item); } }))) .then(getFulfilledValues) .then(result => [].concat(...result)); } function readFiles(files) { return bluebird.settle(files.map(file => myFs.readFileAsync(file))) .then(getFulfilledValues); } async function main(dirname) { return await readFiles(await checkItems(await getItems(dirname))); } main(__dirname) .then(console.log) .catch(console.error);
      
      






All Articles