node.jsを作成する過程で、継続的なIO操作は「ピラミッドナイトメア」につながる可能性があります。コールバック関数の複数のネストにより、コードの維持が困難になります。 CommonJSの約束は、非同期関数をカプセル化し、統一されたチェーンAPIを使用して複数のコールバックの悪夢を取り除くために使用されます。
node.jsによって提供される非ブロッキングIOモデルを使用すると、コールバック関数を使用してIO操作を処理できますが、継続的なIO操作が必要な場合、コールバック関数は複数回ネストされ、コードは美しくなく、維持するのは簡単ではなく、エラー処理のための多くの繰り返しコードがあります。
コードコピーは次のとおりです。
ステップ1(function(value1){
ステップ2(value1、function(value2){
ステップ3(value2、function(value3){
ステップ4(value3、function(value4){
// value4で何かをします
});
});
});
});
これは実際にはnode.jsの制御フローの問題です。この問題には、Async、EventProxyなどの使用など、多くの解決策があります。ただし、この記事のトピックは、CommonJS仕様で約束を使用してこの問題を解決することです。
約束とは何ですか?
CommonJSには多くの種類の約束仕様があります。通常、約束の基本的な動作を定義するPromise/A+仕様について説明します。
約束とは、通常、将来完了する可能性のある非同期操作を表すオブジェクトです。この操作は成功または失敗する可能性があるため、約束のオブジェクトには一般に3つの状態があります。それは、それぞれ未完成の成功した完了と操作の故障を表しています。 Promise Object Objectの状態が保留中から履行または拒否のいずれかに変更されると、その状態を再び変更することはできません。
Promiseオブジェクトには通常、Thenメソッドがあります。これにより、将来の成功の可能性または失敗の理由を返した値を操作できます。これは次のようになります。
Promise.then(onfulfiled、onlejected)
Thenメソッドは、通常2つの関数である2つのパラメーターを受け入れることは明らかです。1つは操作が成功した後に結果を処理するために使用され、もう1つは操作障害の原因を処理するために使用されます。これら2つの関数の最初のパラメーターは、成功後の結果と失敗の原因です。その後のメソッドが関数でない場合、このパラメーターは無視されます。
Then Methodの返品値はPromiseオブジェクトであり、プロセスを制御する効果を実現するために、コールをチェーンコールできます。ここには、値の転送やエラー処理など、多くの詳細があります。約束仕様は次のように定義されています。
onfulfiledまたはonlejected functionの返品値は約束オブジェクトではありません。値は、次のメソッドでは、onfulfiledの最初のパラメーターとして使用されます。返品値が約束のオブジェクトである場合、Then Methodの返品値はどのようにPromiseオブジェクトになることができますか
例外がだけだに充実した機能またはreferedの関数にスローされた場合、then method returned promiseオブジェクトのステータスが拒否されるように変換されます。 Promiseオブジェクトが呼び出される場合、エラーオブジェクトは、前提条件の関数の最初のパラメーターとして使用されます。
Promise状態が履行され、その後の方法で整理された関数が提供されない場合、Then Methodによって返されるPromise Object Stateが満たされ、成功した結果は以前の約束の結果です。
追加するために、整理されていないと延期された両方が非同期に実行されます。
仕様の実装:Q
上記は約束の仕様に関するものであり、必要なのはその実装です。 Qは、Promise/a+の実装仕様を改善するライブラリです。
まず、約束オブジェクトを作成する必要があります。 Promise Objectの作成の仕様はPromise/bです。ここでは詳細に説明しません。コードを追加するだけです。
コードコピーは次のとおりです。
function(flag){
var defer = q.defer();
fs.readfile( "a.txt"、function(err、data){
if(err)defer.reject(err);
else defer.resolve(data);
});
Defer.Promiseを返します。
}
ほとんどの約束の実装は、約束の作成に似ています。 Promise属性を備えたDeferオブジェクトを作成することにより、値が正常に取得された場合、Defer.Resolve(値)が呼び出され、障害がある場合、Defer.Reject(理由)が呼び出され、最後にDeferのPromise属性を返します。このプロセスは、defer.resolveを呼び出すこととして理解できます。
一連の連続的な非同期方法に直面しているとき、約束を使用して美しいコードをどのように書くことができますか?次の例を見てください。
コードコピーは次のとおりです。
promise0.then(function(result){
// dosomhings
返品結果;
})。then(function(result){
// dosomhings
promise1を返す;
})。then(function(result){
// dosomhings
})。catch(function(ex){
console.log(ex);
})。最後に(function(){
console.log( "final");
});
上記のコードでは、ThenメソッドはOnfulFiledのみを受け入れ、CATCHメソッドは実際には(null、Onrejected)です。このように、一連の非同期メソッドが常に正常に値を返す限り、コードは滝スタイルで下方に実行されます。非同期メソッドのいずれかが失敗するか、例外が発生した場合、CommonJS Promiseの仕様に従って、キャッチの関数が実行されます。 Qは最終的にメソッドを提供します。これは、文字通り理解しやすい、つまり、解決または拒否するかどうかにかかわらず、最終的に機能します。
見た目が良く、コードはより維持されており、美しいので、同時性が必要な場合はどうなりますか?
コードコピーは次のとおりです。
Q.all([Promise0、Promise1、Promise2])。spread(function(val0、val1、val2){
console.log(arguments);
})then(function(){
console.log( "done");
})。catch(function(err){
console.log(err);
});
Qは同時性のAPIも提供し、すべてのメソッドを呼び出し、約束アレイを渡すことで、Thenのチェーンスタイルを引き続き使用できます。 Q.nfbindなどの良いこともあります。これは、node.jsのネイティブAPIをコード形式を統合することを約束に変換できます。より多くのAPIはここで詳しく説明しません。
結論は
この記事では、主にnode.js制御フローの問題を解決するための約束の使用を紹介しますが、フロントエンドにも約束を適用することができます。 EMCAScript6は、ネイティブAPIサポートを提供しています。約束が唯一の解決策ではなく、Asyncも良い選択であり、より友好的な並行性コントロールAPIを提供することを指摘する必要がありますが、非同期方法で関数をカプセル化する場合、約束にはより多くの利点があると思います。
さて、それはこの記事のすべてです、私はそれがすべての人に役立つことを願っています。