コールバック地獄
JavaScriptプログラマーの場合、コールバックの処理は家庭的ですが、レベルが深すぎるコールバックの取り扱いはそれほど美しくありません。次のサンプルコードスニペットでは、3層コールバックを使用してから、シーンのより多くの層のために脳を補充します。それは単に酸っぱいです。これは伝説的なコールバック地獄です。
getDirectories(function(dirs){getFiles(dirs [0]、function(files){getContent(files [0]、function(file、content){console.log( 'filename:'、file); console.log(content);});});}); function getDirectories(callback){setimeout(function(){callback(['/home/ben']);}、1000);} function getFiles(dir、callback){function(){callback([dir + '/test1.txt'、dir + '/test2.txt'); setimeout(function(){callback(file、 'content');}、1000)}解決
エコシステムには、ブルーバード、Qなどのコールバックヘルの問題に対処できる多くの非同期ソリューションがあります。この記事では、ECMAScript 6/7仕様の非同期プログラミングのサポートに焦点を当てています。
ES6の約束
Promiseは、非同期プログラミングのソリューションであり、コールバックHellの問題を解決するための強力なツールです。
Dojo.Deferredの機能を追加した2007年に、JavaScriptエコシステムで主流に約束が受け入れられました。 Dojo.Deferredの人気により、2009年にKris ZypはCommonJSの約束/仕様を提案しました。その後、Q.JS、FuturesJsなどを含むエコシステムに多数の約束の実装が登場しました。もちろん、約束の人気は主にJQueryの存在によるものですが、JQueryはCommonJS Promises/Aの仕様に完全に準拠していません。次に、ご覧のとおり、ES 6仕様には約束が含まれます。
約束はMDNで次のように説明されています。
Promiseオブジェクトは、Promiseオブジェクトが作成されたときに知られていない場合があります。非同期操作の成功または失敗の取り扱い方法を指定できます。これにより、非同期方式は同期方法のような値を返すことができます:非同期メソッドは元の返品値を含むことを返します
次のコードは、Promiseを通じて実装された「Callback Hell」セクションの例です。コードはあまり簡潔に見えませんが、従来の階層コールバックと比較して大幅に改善されており、コードはより保守可能で読みやすくなります。
getDirectories()。then(function(dirs){return getFiles(dir [0]);})。 function getDirectories(){return new Promise(function(resolve、requed){setimeout(function(){resolve(['/home/ben']);}、1000);} function getfiles(dir){return new promise(function(resolve、拒否){setimeout(){dir + '/test1.t' nt 'nt' 'nt' nt 'nt' nt 'nt' ben '/test2.txt']);ES6ジェネレーター
約束の実装は十分に単純ではありませんが、より良い選択が必要であり、COは選択肢の1つです。 COは、発電機に基づいた非同期フローコントローラーです。 COを理解する前に、最初に発電機を理解する必要があります。 C#に精通している学生は、C#2.0バージョンがジェネレーターを反復するための利回りキーワードを導入することをすべて理解する必要があります。 ES 6ジェネレーターはC#に似ており、収量の構文糖も使用し、状態マシンを内部的に実装しています。特定の使用については、MDNドキュメント関数*セクションを参照し、ジェネレーターの詳細な理解については、AlloyTeamチームブログを参照してください。 COを使用してES6ジェネレーターとES6の約束を巧みに組み合わせて、非同期呼び出しをより調和させます。
co(function*(){var dirs = hird getDirectories(); var files = hird getFiles(dirs [0]); var contentval = hird getContent(files [0]); console.log( 'filename:'、contentval.file); console.log(contentsval.content);});COは非常に賢く、そのコアコードは次の例を簡素化できます。一般的なアイデアは、状態が完成するまで再帰的なトラバーサルジェネレーターを使用することです。もちろん、COはより多くを行います。
Rungenerator(); function* run(){var dirs = evelow getDirectories(); var files = hired getFiles(dirs [0]); var contentval = hired getContent(files [0]); console.log( 'filename:'、contentval.file); console.log(contentval.content);} function rungenerator(){var gen = run(); function go(result){if(result.done)return; result.value.then(function(r){go(gen.next(r));}); } go(gen.next());}ES7 ASYNC/待ち望んでいます
ES6ジェネレーターは本当に良いですが、サードパーティライブラリのサポートが必要であることは残念です。良いニュースは、ES 7が非同期呼び出しの問題を完全に解決するためにAsync/待望のキーワードを導入することです。まあ、.NETは一歩先を進んでおり、.NETフレームワーク4.5はすでにそれを最初にサポートしています。
将来のコードは次のように記述されます:
run(); async function run(){var dirs = await getDirectories(); var files = await getFiles(dirs [0]); var contentval = await getContent(files [0]); console.log( 'filename:'、contentval.file); console.log(contentval.content);}結論は
古典的なコールバック非同期プログラミング方法から、ES6プロミス仕様による非同期プログラミングの改善、ESジェネレーターとの共継続のエレガントな処理、そして最後にES7 Async/待望の完璧な終了まで、ECMAScriptがこれらの特徴を持ち、どのような問題を解決するのかを理解することができ、Javascript Asynchronousプログラミングの開発をより明確に見ることができます。