2016-12-25 17 views
0

私はブルーバードで約束を使用してmysqlクエリを送信し、制御フローを管理します&エラー。ここでは、次のようになります。ノード約束制御フロー

sendQuery1(..) 
.then(sendQuery2(..)) 
.then(function(results from last query){ 
    if(rain){ 
     res.render(...) 
    }else{ 
     /* 
      I need to send additional 2 queries here 
     */ 
    } 
}).catch(errors); 

約束チェーンは非常に便利ですが、私は、複数のサブチェーンが内側にある場合はエラー処理が厄介になりますが分かりました。

ここで、私はおそらく内部で以下の記述する必要がある/ * */

return sendQuery3(..) 
     .then(sendQuery4(..)) 
     .then(function(..){ 
      res.render(".....") 
     }).catch(error2); 

問題のこのタイプを処理するために、任意のより良い方法はありますか?

+1

どのnodejsバージョンを使用していますか? – Shaharyar

+0

正確に何が問題になっていますか?エラー処理はどのように乱雑になるのでしょうか? – dfsq

答えて

0

あなたはエラーをキャッチしますが、あなたのコードに問題はありません。うん、それは厄介な取得ができますが、クリーンなコードを維持し、まだあなたのロジックを実装するには、次のアプローチで行くことができます。

sendQuery1(..) 
.then(sendQuery2(..)) 
.then(function(results from last query){ 
    if(rain){ 
     res.render(...) 
     throw new Error('breakChain'); //intentionally throwing error to skip the remaining chain 
    } 
    return; //will act like 'else' 
}) 
.then(sendQuery3(..)) 
.then(sendQuery4(..)) 
.catch(function (e) { 
    if(e.message != 'breakChain') //act on error if it was other than 'breakChain' 
     throw e; 
}); 
+0

@pano - エラー以外の条件の合成エラーは素晴らしいデザインパターンではなく、ちょうど1つのフラットチェーンではなくチェーンを分岐する必要があることを示しています。チェーンを分岐する方法を示す回答を提供しました。 – jfriend00

+0

FYI、これは動作しません: 'sendQuery1(..) .then(sendQuery2(..))'。 'sendQuery1(..)'が 'sendQuery2(..)'を呼び出す前に 'sendQuery1(..)'が完了するまで待たずに、2番目のクエリで最初のクエリの結果を使うことはできません。私はOPがそういうことを示していたのを知っていますが、それは正しくなく、正しく動作しません。 – jfriend00

+0

@ jfriend00ここであなたの言葉を引用すると、OPのサンプルコードへの疑似a/cです。彼は答えを受け入れたので、彼は約束の基本がどのように働くかを知っていると思う。彼に問題があったら、それについて尋ねたでしょう。 – Shaharyar

2

私はここにあなたの問題を正確には見当たりません。チェーン内にチェーンがある場合(通常そうではありませんが、そこでは自分のアーキテクチャをチェックする必要があります)、表示されているようなエラーをキャッチするだけです。

グローバル(またはローカル)エラーハンドラ関数を使用してcatch関数に渡すことをお勧めします。したがって、複数のキャッチがあっても、同じエラーハンドラを使用できます。

私の意見では、最良のソリューションは、 "promise chain bypass"を作成することです。したがって、catchを使用して条件に基づいて特定の部分をスキップしてください。これがあなたが探しているものでない場合は、問題を明記してください。

+0

こんにちはNikxDa、迅速な対応に感謝します。 「約束のバイパス」の詳細を教えてください。私はグローバルエラーハンドラが動作することを知っているが、私はまだ各チェーン内のサブチェーンを含むすべての約束チェーンにキャッチエラーを添付する必要がある、それは私が苦労している問題だ – Pano

+0

バイパスは意図的にエラーを投げ、Shaharyar回答。その後、他の「then」部分をスキップして、続行できる場所から直接キャッチにジャンプすることができます。この方法では、ネストされた条件は必要ありません。 – NikxDa

+0

ありがとうございました。私は2つの正解を選ぶことができないことを申し訳なく思う。 – Pano

0

あなたはここで議論されているどのようないくつかの論理条件に基づいて、チェーンの分岐されます。チェーンの残りの部分を中止するだけでエラーを投げるのではなく、実際にチェーンを分岐させる方が一般的には良い方法です。これは、Shaharyarが実際にはエラーではないエラーを合成することを提案したスキームではなく、エラーとしてエラーを保持します。

あなたはこのよう.then()ハンドラ内から新しい約束チェーンを返すことでチェーンを分岐することができます

FYI
sendQuery1(..).then(function(r1) { 
    return sendQuery2(...); 
}).then(function(r2){ 
    if (rain){ 
     // processing is done, so just render 
     res.render(...) 
    } else { 
     // return promise here to attach this new branch to the original chain 
     return sendQuery3(..).then(sendQuery4).then(function() { 
      // process last query 
     }); 
    } 
}).catch(errors); 

、あなたは擬似コードではなく、実際のコードのみを掲載しましたし、私たちができないので、作業を実行するためにどの機能が以前の結果にアクセスする必要があるかを見ると、コードを完全に最適化することはできません。これは、ブランチングがプロミスチェーン内でどのように機能するかの例を示すためです。それはおそらくあなたが使いたい原則です。実際のコードを表示すると、より具体的かつ最適化された回答を提供することができます。

+0

コードをきれいにするには、いくつかの設計変更を行う必要があります。あなたのアプローチは良いですが、コードは伝統的なコールバックのように非常に乱雑に見えます。私は発電機を好むが、OPは彼が持っているノードのバージョンを知らないので、約束が適切と思われる。 – Shaharyar

+0

@Shaharyar - OPはちょうど疑似コードをポストしているので、正確なコードについては正確ではありません。これは、(偽のエラーを作成する代わりに)分岐がどのように機能するかを示し、実際のコードの機能は、呼び出し元の実際の関数が矢印関数などをサポートしているかどうかに関して最適化できます。おそらくより良いデザインパターンとして。 – jfriend00

+0

@Shaharyar - そして、もしあなたがこの 'sendQuery1(..) .then(sendQuery2(..))'のようなスタイルコードを参照していたのなら、これを行うためのよりクリーンな方法として、うまくいきません。それは 'sendQuery1()'が 'sendQuery2()'を呼び出すために行われ、 'sendQuery2()'の引数で 'sendQuery1()'の結果を使用できなくなるまで待たないでしょう。 – jfriend00