ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript 非同期プログラミング: 非同期データ収集の具体的な方法_JavaScript スキル

JavaScript 非同期プログラミング: 非同期データ収集の具体的な方法_JavaScript スキル

WBOY
WBOYオリジナル
2016-05-16 17:25:131019ブラウズ

Asyncjs/seriesByHand.js

コードをコピー コードは次のとおりです。

var fs = require('fs') ;
process.chdir('recipes') // 作業ディレクトリを変更します
var concatenation = '';

fs.readdir('.', function(err, filenames) {
if (err) throw err;

function readFileAt(i) {
var filename = filenames[i];
fs.stat(filename, function(err, stats) {
if (err) throw err;
if (! stats.isFile()) return readFileAt(i 1);

fs.readFile(filename, 'utf8', function(err, text) {
if (err) throw err;
concatenation = text;
if (i 1 === filenames.length ){


ご覧のとおり、非同期バージョンには同期バージョンよりもはるかに多くのコードがあります。 filter や forEach などの同期メソッドを使用すると、コードの行数は約半分で済み、非常に読みやすくなります。これらの気の利いたイテレーターの非同期バージョンがあればどんなに素晴らしいでしょう。それを行うには Async.js を使用してください。



いつ捨てても大丈夫ですか?

上記のコード例で、作成者がセクション 1.4 で提供したアドバイス (特に運用環境では、コールバックから例外をスローするのは悪い設計である) を無視していることに気づいたかもしれません。ただし、直接例外をスローする単純な例では問題ありません。コード内で予期しないエラーが発生した場合、 throw はコードをシャットダウンし、エラーの原因を説明する適切なスタック トレースを提供します。

ここで本当に問題なのは、同じエラー処理ロジック (つまり、if(err) throw err) が 3 回も繰り返されていることです。セクション 4.2.2 では、Async.js がこの重複を減らすのにどのように役立つかを見ていきます。

Async.jsの関数記述方法

同期反復子で使用されるfilterとforEachメソッドを、対応する非同期メソッドに置き換えたいと考えています。 Async.js には 2 つのオプションがあります。

async.filter と async.forEach は、指定された配列を並列処理します。

async.filterSeries と async.forEachSeries は、指定された配列を順番に処理します。

これらの非同期操作を並行して実行すると高速になるはずですが、なぜシーケンシャルなアプローチを使用するのでしょうか?理由は 2 つあります。

前述した、ワークフローの順序が予測できないという問題。確かに、最初に結果を配列に格納してから、その配列を結合してこの問題を解決することもできますが、結局のところ、これはもう 1 つのステップです。

Node と他のアプリケーション プロセスが同時に読み取ることができるファイルの数には上限があります。この上限を超えると、オペレーティング システムはエラーを報告します。ファイルを順番に読み取ることができる場合は、この制限を心配する必要はありません。

それでは、まず async.forEachSeries について理解しましょう。以下ではAsync.jsのデータ収集メソッドを使用しており、同期版のコード実装を直接書き換えています。


Asyncjs/forEachSeries.js



コードをコピー

コードは次のとおりです。

var async = require('async') ;

var fs = require('fs');process.chdir('recipes') // 作業ディレクトリを変更しますvar concatenation = ''; var dirContents = fs.readdirSync('.'); async.filter(dirContents, isFilename, function(filenames) {
async.forEachSeries(filenames, readAndConcat, onComplete);
});

function isFilename(filename, callback) {
fs.stat(filename, function(err, stats) {
if (err) throw err; callback(stats.isFile());

});

}


function readAndConcat(filename, callback) {
fs.readFile(filename, 'utf8', function(err, fileContents) {

if (err) return callback(err);

concatenation = fileContents ;
コールバック();
});
}

function onComplete(err) {

if (err) throw err;

console.log(concatenation);
}


これで、私たちのコードは 2 つの部分に見事に分割されました: タスクの概要 (async.filter 呼び出しと async.forEachSeries 呼び出しの形式) と実装の詳細 (2 つのイテレーター関数と完了コールバック onComplete の形式)。

標準の関数反復メソッドに対応する Async.js ユーティリティ関数は、

filter と forEach だけではありません。 Async.js は次のメソッドも提供します:

reject/rejectSeries、フィルターの逆、
map/mapSeries、1:1 変換、
reduce/reduceRight、値の段階的な変換。フィルター;
sortBy、順序付けされたコピーを作成します。
some、少なくとも 1 つの値が指定された基準を満たすかどうかをテストします。
every、すべての値が指定された基準を満たすかどうかをテストします。
これらのメソッドは Async.js の本質であり、コードの重複を最小限に抑えながら一般的な反復作業を実行できるようにします。より高度なメソッドの検討を続ける前に、これらのメソッドのエラー処理手法を見てみましょう。

Async.js エラー処理テクノロジー

それを責めたいなら、これを最初に実行した Node の fs.exists を責めてください。これは、Async.js データ収集メソッド (filter/filterSeries、reject/rejectSeries、detect/detectSeries、some、every など) を使用するイテレーターがエラーを報告できないことも意味します。

ブール値ではないすべての Async.js イテレータの場合、イテレータ コールバックの最初のパラメータとして非 null/未定義値を渡すと、エラー値を使用して完了コールバックが即座に呼び出されます。これが、readAndConcat が throw なしで動作する理由です。

Asyncjs/forEachSeries.js

コードをコピー コードは次のとおりです。
function readAndConcat(filename, callback) {
fs .readFile(filename, 'utf8', function(err, fileContents) {
if (err) return callback(err);
concatenation = fileContents;
callback();
} );
}

したがって、callback(err) が readAndConcat で実際に呼び出された場合、この err は完了コールバック (つまり、onComplete) に渡されます。 Async.js は、onComplete が最初のエラーによって呼び出されたのか、すべての操作が正常に完了したときに呼び出されたのかに関係なく、onComplete が 1 回だけ呼び出されるようにすることのみを担当します。
Asyncjs/forEachSeries.js

コードをコピーします コードは次のとおりです。
function onComplete(err) {
if (err ) throw err;
console.log(concatenation);
}

ノードのエラー処理規則は、Async.js データ収集メソッドには理想的ではないかもしれませんが、Async には理想的ではありません。 js の他のすべてのメソッドと同様に、これらの規則に従うことで、エラーが各タスクから完了コールバックにきれいに流れることができます。次のセクションで、この例をさらに見ていきます。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。