ホームページ >ウェブフロントエンド >jsチュートリアル >Promise を使用して NodeJS_node.js で非同期関数をカプセル化する

Promise を使用して NodeJS_node.js で非同期関数をカプセル化する

WBOY
WBOYオリジナル
2016-05-16 16:13:001123ブラウズ

Node.js の作成プロセスでは、継続的な IO 操作が「ピラミッドの悪夢」につながる可能性があります。コールバック関数の複数のネストにより、コードの保守が困難になります。CommonJs の Promise を使用して非同期関数をカプセル化し、統合されたチェーン API を使用します。複数のコールバックの悪夢を取り除くためです。

Node.js が提供するノンブロッキング IO モデルでは、コールバック関数を使用して IO 操作を処理できますが、継続的な IO 操作が必要な場合、コールバック関数が複数回ネストされ、コードが非常に見苦しく、困難になります。また、エラー処理のための重複コード、いわゆる「破滅のピラミッド」が大量に存在する可能性があります。

コードをコピーします コードは次のとおりです:

step1(関数 (値1) {
Step2(値1, 関数(値2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// value4
で何かを行う });
});
});
});

これは実際には Node.js の制御フローの問題です。この問題には、async やeventProxy の使用など、多くの解決策があります。ただし、この記事のテーマは、CommonJs 仕様の Promise を使用してこれを解決することです。問題。

約束とは何ですか?

CommonJ には多くの Promise 仕様がありますが、一般的には Promise の基本的な動作を定義する Promise/A 仕様について説明します。

Promise は、通常、将来完了する可能性のある非同期操作を表すオブジェクトです。この操作は成功することも失敗することもあるため、Promise オブジェクトには通常、保留中、履行済み、拒否済みの 3 つの状態があります。それぞれ、不完全、正常に完了、および操作の失敗を表します。 Promise オブジェクトの状態が Pending から Fulfilled または Rejected に変わると、その状態を変更することはできません。

Promise オブジェクトには通常、then メソッドがあり、将来成功する可能性がある後に返される値や失敗の理由を操作できます。 then メソッドは次のようになります:

promise.then(onFulfilled, onRejected)
明らかに、then メソッドは 2 つのパラメーターを受け入れます。通常、1 つは操作が成功した後の結果を処理するために使用され、もう 1 つは操作が失敗した後の理由を処理するために使用されます。はそれぞれ成功後の結果と失敗の理由です。 then メソッドに渡されたパラメータが関数ではない場合、このパラメータは無視されます。

then メソッドの戻り値は Promise オブジェクトです。この機能により、then を連鎖呼び出ししてフローを制御する効果を得ることができます。ここには、値の転送やエラー処理など、詳細な問題が数多くあります。 Promise の仕様は次のように定義されています:

onFulfilled または onRejected 関数の戻り値は Promise オブジェクトではありません。この値は、次の then メソッドで onFulfilled の最初のパラメーターとして使用されます。戻り値が Promise オブジェクトである場合、その戻り値は次のとおりです。 then メソッドの Promise オブジェクトは? onFulfilled 関数または onRejected 関数で例外がスローされた場合、then メソッドによって返される Promise オブジェクトのステータスは Rejected に変更されます。Promise オブジェクトが then を呼び出すと、Error オブジェクトが onRejected 関数の最初のパラメータとして使用されます。
Promise ステータスが Fulfilled になり、then メソッドに onFulfilled 関数が指定されていない場合、then メソッドによって返される Promise オブジェクトのステータスは Fulfilled になり、成功した結果は前の Promise の結果になります。これは Rejected にも当てはまります。
さらに、onFulfilled と onRejected は非同期で実行されます。

標準実装: q

上記は Promise の仕様であり、必要なのはその実装です。q は Promise/A のより優れた実装仕様を備えたライブラリです。

まず、Promise オブジェクトを作成する必要があります。Promise オブジェクトの作成に関する仕様は、ここでは詳しく説明しません。コードを参照してください。

コードをコピーします コードは次のとおりです:
関数(フラグ){
var defer = q.defer();
fs.readFile("a.txt", function(err, data){
If(err) defer.reject(err);
else defer.resolve(data);
});
return defer.promise;
}

Promise のほとんどの実装は、Promise 属性を使用して defer オブジェクトを作成することで、値の取得に成功した場合は defer.resolve(value) が呼び出され、失敗した場合は defer.reject(reason) になります。 ) が呼び出され、defer の Promise 属性が返されます。このプロセスは、defer.resolve を呼び出して Promise のステータスを Fulfilled に変更し、defer.reject を呼び出して Promise のステータスを Rejected に変更すると理解できます。

一連の連続的な非同期メソッドに直面したとき、Promise を使用して美しいコードを記述するにはどうすればよいでしょうか?以下の例を見てください。

コードをコピーします コードは次のとおりです:

promise0.then(関数(結果){
// 何かをする
結果を返します;
}).then(関数(結果) {
// 何かをする
Promise1 を返す; }).then(関数(結果) {
// 何かをする
}).catch(関数(例) {
console.log(ex);
}).finally(function(){
console.log("最終");
});

上記のコードでは、then メソッドは OnFulfilled のみを受け入れ、catch メソッドは実際には then(null, OnRejected) です。この場合、一連の非同期メソッドが常に正常に値を返す限り、コードは次のようになります。下向きに実行すると、非同期メソッドのいずれかが失敗するか例外が発生した場合、CommonJs Promise 仕様に従って、catch 内の関数が実行されます。 q には、finally メソッドも用意されています。これは文字通りに理解するのが簡単です。つまり、resolve または拒否に関係なく、finally の関数が実行されます。

これは良いことのように思えます。コードはより保守しやすく、美しいものになっています。では、並行性が必要な場合はどうすればよいでしょうか?

コードをコピーします コードは次のとおりです:
q.all([約束0, 約束1, 約束2]).spread(function(val0, val1, val2){
console.log(引数);
}).then(function(){
console.log("完了");
}).catch(function(err){
console.log(err);
});

Q は同時実行用の API も提供します。all メソッドを呼び出して Promise 配列を渡して、そのチェーン スタイルの使用を継続します。 Node.jsのネイティブAPIをPromiseに変換してコード形式を統一できるq.nfbindなどもあり、これも非常に優れています。その他の API については、ここでは詳しく説明しません。

結論

この記事では主に Node.js 制御フローの問題を解決するための Promise の使用法を紹介しますが、EMCAScript6 はネイティブ API サポートを提供しており、Promise をフロントエンドに適用することもできます。 Promise が唯一の解決策ではなく、より使いやすい同時実行制御 API を提供する async も良い選択肢であることを指摘しておく必要があります。ただし、非同期メソッドで関数をカプセル化する場合には Promise の方が利点があると思います。

さて、この記事はここで終わります。皆さんのお役に立てれば幸いです。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。