私はまだ約束にかなり慣れておらず、現在bluebirdを使用していますが、それをどのように処理するのが最善かわからないシナリオがあります。
たとえば、Expressアプリ内に次のようなプロミスチェーンがあります。
repository.Query(getAccountByIdQuery)
.catch(function(error){
res.status(404).send({ error: "No account found with this Id" });
})
.then(convertDocumentToModel)
.then(verifyOldPassword)
.catch(function(error) {
res.status(406).send({ OldPassword: error });
})
.then(changePassword)
.then(function(){
res.status(200).send();
})
.catch(function(error){
console.log(error);
res.status(500).send({ error: "Unable to change password" });
});
したがって、私が求めている動作は次のとおりです。
ですから、現在の漁獲量は連鎖を止めていないようで、それは理にかなっているので、エラーに基づいてチェーンを特定の時点で強制的に停止させる方法があるのか、それとももっと良い方法があるのか疑問に思います。の場合があるように、これを構造化して、何らかの形の分岐動作を取得しif X do Y else Z
ます。
どんな助けでも素晴らしいでしょう。
この動作は、同期スローとまったく同じです。
try{
throw new Error();
} catch(e){
// handle
}
// this code will run, since you recovered from the error!
これは、.catch
エラーから回復できるようにするためのポイントの半分です。状態がまだエラーであることを通知するために、再スローすることが望ましい場合があります。
try{
throw new Error();
} catch(e){
// handle
throw e; // or a wrapper over e so we know it wasn't handled
}
// this code will not run
ただし、エラーは後のハンドラーによってキャッチされるため、これだけでは機能しません。ここでの本当の問題は、一般化された「HANDLE ANYTHING」エラーハンドラーは一般に悪い習慣であり、他のプログラミング言語やエコシステムでは非常に嫌われているということです。このため、Bluebirdは型付きおよび述語のキャッチを提供します。
追加の利点は、ビジネスロジックが要求/応答サイクルをまったく認識している必要がない(そして認識してはならない)ことです。クライアントが取得するHTTPステータスとエラーを決定するのはクエリの責任ではなく、後でアプリが大きくなるにつれて、ビジネスロジック(DBのクエリ方法とデータの処理方法)をクライアントに送信するものから分離することをお勧めします。 (どのhttpステータスコード、どのテキスト、どの応答)。
これが私があなたのコードを書く方法です。
まず、Bluebirdがすでに提供しているサブクラス.Query
をスローします。エラーをサブクラス化する方法がわからない場合は、お知らせください。NoSuchAccountError
Promise.OperationalError
さらにそれをサブクラス化してAuthenticationError
から、次のようなことを行います。
function changePassword(queryDataEtc){
return repository.Query(getAccountByIdQuery)
.then(convertDocumentToModel)
.then(verifyOldPassword)
.then(changePassword);
}
ご覧のとおり、非常にきれいで、プロセスで何が起こっているかについての取扱説明書のようにテキストを読むことができます。また、要求/応答からも分離されています。
さて、私はそれをルートハンドラーからそのように呼びます:
changePassword(params)
.catch(NoSuchAccountError, function(e){
res.status(404).send({ error: "No account found with this Id" });
}).catch(AuthenticationError, function(e){
res.status(406).send({ OldPassword: error });
}).error(function(e){ // catches any remaining operational errors
res.status(500).send({ error: "Unable to change password" });
}).catch(function(e){
res.status(500).send({ error: "Unknown internal server error" });
});
このように、ロジックはすべて1つの場所にあり、クライアントへのエラーを処理する方法の決定はすべて1つの場所にあり、それらは互いに乱雑になりません。
.catch
try-catch
ステートメントのように機能します。つまり、最後に1つのキャッチのみが必要です。
repository.Query(getAccountByIdQuery)
.then(convertDocumentToModel)
.then(verifyOldPassword)
.then(changePassword)
.then(function(){
res.status(200).send();
})
.catch(function(error) {
if (/*see if error is not found error*/) {
res.status(404).send({ error: "No account found with this Id" });
} else if (/*see if error is verification error*/) {
res.status(406).send({ OldPassword: error });
} else {
console.log(error);
res.status(500).send({ error: "Unable to change password" });
}
});
エラーに基づいて、チェーンを特定のポイントで強制的に停止させる方法があるかどうか疑問に思っています
いいえ。チェーンの最後までバブルする例外をスローしない限り、チェーンを実際に「終了」することはできません。その方法については、BenjaminGruenbaumの回答を参照してください。
彼のパターンの導出は、エラーの種類を区別しますが、持っていたエラーを使用していないだろうstatusCode
し、body
単一の汎用から送ることができるフィールド.catch
ハンドラを。ただし、アプリケーションの構造によっては、彼のソリューションの方がクリーンな場合があります。
または、これを構造化して何らかの形の分岐動作を取得するためのより良い方法がある場合
はい、promiseを使用して分岐を行うことができます。ただし、これは、チェーンを離れてネストに「戻る」ことを意味します。ネストされたif-elseまたはtry-catchステートメントで行うのと同じです。
repository.Query(getAccountByIdQuery)
.then(function(account) {
return convertDocumentToModel(account)
.then(verifyOldPassword)
.then(function(verification) {
return changePassword(verification)
.then(function() {
res.status(200).send();
})
}, function(verificationError) {
res.status(406).send({ OldPassword: error });
})
}, function(accountError){
res.status(404).send({ error: "No account found with this Id" });
})
.catch(function(error){
console.log(error);
res.status(500).send({ error: "Unable to change password" });
});
私はこのようにしてきました:
あなたは最後にあなたのキャッチを残します。そして、チェーンの途中でエラーが発生したときにエラーをスローします。
repository.Query(getAccountByIdQuery)
.then((resultOfQuery) => convertDocumentToModel(resultOfQuery)) //inside convertDocumentToModel() you check for empty and then throw new Error('no_account')
.then((model) => verifyOldPassword(model)) //inside convertDocumentToModel() you check for empty and then throw new Error('no_account')
.then(changePassword)
.then(function(){
res.status(200).send();
})
.catch((error) => {
if (error.name === 'no_account'){
res.status(404).send({ error: "No account found with this Id" });
} else if (error.name === 'wrong_old_password'){
res.status(406).send({ OldPassword: error });
} else {
res.status(500).send({ error: "Unable to change password" });
}
});
他の関数はおそらく次のようになります。
function convertDocumentToModel(resultOfQuery) {
if (!resultOfQuery){
throw new Error('no_account');
} else {
return new Promise(function(resolve) {
//do stuff then resolve
resolve(model);
}
}
おそらくパーティーに少し遅れますが、.catch
ここに示すようにネストすることは可能です:
Mozilla DeveloperNetwork-Promisesの使用
編集:一般的に求められている機能を提供するため、これを提出しました。ただし、この特定のケースではそうではありません。すでに他の人が詳細に説明しているように.catch
、エラーを回復することになっているからです。たとえば、明示的なものがない場合はそれを解決するため、複数の .catch
コールバックでクライアントに応答を送信することはできません。その場合、チェーンが実際に解決されていなくてもトリガーが続行され、フォローがトリガーされて送信される可能性があります。クライアントへの別の応答。エラーを引き起こし、おそらくあなたの道を投げます。この複雑な文章があなたにとって意味のあるものであることを願っています。.catch
return
undefined
.then
.catch
UnhandledPromiseRejection
.then().catch()...
あなたの代わりに行うことができます.then(resolveFunc, rejectFunc)
。この約束の連鎖は、途中で物事を処理した方がよいでしょう。これが私がそれを書き直す方法です:
repository.Query(getAccountByIdQuery)
.then(
convertDocumentToModel,
() => {
res.status(404).send({ error: "No account found with this Id" });
return Promise.reject(null)
}
)
.then(
verifyOldPassword,
() => Promise.reject(null)
)
.then(
changePassword,
(error) => {
if (error != null) {
res.status(406).send({ OldPassword: error });
}
return Promise.Promise.reject(null);
}
)
.then(
_ => res.status(200).send(),
error => {
if (error != null) {
console.error(error);
res.status(500).send({ error: "Unable to change password" });
}
}
);
注:これif (error != null)
は、最新のエラーを処理するためのちょっとしたハックです。
上記のBenjaminGruenbaumの答えは、複雑な論理シーケンスの最良の解決策だと思いますが、これがより単純な状況に対する私の代替案です。私はちょうど使用errorEncountered
と一緒に旗をreturn Promise.reject()
後続スキップするthen
かcatch
の文を。したがって、次のようになります。
let errorEncountered = false;
someCall({
/* do stuff */
})
.catch({
/* handle error from someCall*/
errorEncountered = true;
return Promise.reject();
})
.then({
/* do other stuff */
/* this is skipped if the preceding catch was triggered, due to Promise.reject */
})
.catch({
if (errorEncountered) {
return;
}
/* handle error from preceding then, if it was executed */
/* if the preceding catch was executed, this is skipped due to the errorEncountered flag */
});
2つ以上のthen / catchペアがある場合は、おそらくBenjaminGruenbaumのソリューションを使用する必要があります。しかし、これは簡単なセットアップで機能します。
スキップする必要のある後続がないため、ファイナルにcatch
はではreturn;
なくのみがあることに注意してください。これは、ノードが好まない未処理のPromise拒否としてカウントされます。上に書かれているように、決勝戦は平和的に解決された約束を返します。return Promise.reject();
then
catch
特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。
ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。
ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。
サンディエゴコミックコンは今週開幕し、オタクのアナウンス、ポスター、予告編、お気に入りの番組や映画のからかいでいっぱいになります。SDCCは、コンベンションフロア全体の多くのパネルで行われているため、すべてに対応するのは難しい場合があります。
小さなアプリ開発者は金曜日に発表された法的な和解でグーグルから9千万ドルをこじ開けた。アップルとの同様の合意に続いて熱くなった。金曜日のブログ投稿で、Googleは、Androidメーカーが市場での優位性を悪用してPlayストア経由でのアプリ内購入に対して30%の料金を不当に請求したと主張するアプリ開発者との訴訟を解決するために、9千万ドルを支払うことに合意したと述べました。
今週、RadioShackのTwitterアカウントは、奇妙なものから完全にひどいものになりました。短い順序で、会社のフィード全体が、バイブレーター、「ビッグティット」(スペルミス)、有名人やその他の企業アカウントを荒らしているツイートなど、NSFW素材の真の山になりました。
大型ハドロン衝突型加速器のトンネル内にあるコンパクトミュオンソレノイド(CMS)検出器。2012年7月4日、CERNの科学者たちは、1960年代に最初に提案された素粒子であるヒッグス粒子の観測を確認しました。
Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday
シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。
オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。
Bien. Hay un momento en toda salida al espacio exterior en el que de la tensión, la velocidad y las altas temperaturas derivadas del cruce de estratosfera a ionosfera se pasa a un momento de súbita calma, donde se despliega la vista completa del paisaje espacial que nos rodea.
1.ドラマを見た後、起業する考えはありますか?あなたのビジネスはボトルネックに遭遇しましたか?方向性がなくてわからない場合は、ドラマを追いかけて行くことを心からお勧めします。(?)ブラフではなく、最も完璧なビジネス例を隠すドラマがあります。2.ブレイキング・バッドとその弁護士ドラマ「ブレイキング・バッド」を見た友人たちは、演劇の中で、穏やかな表情で、弁護士のソウル・グッドマンに深く感銘を受けなければなりません。口を開けて、感覚の弱い傭兵の性格を持っています。道徳の面で、サル・グッドマンは無意識のうちに劇に欠かせない役割を果たし、彼自身のシリーズ「絶望的な弁護士」(ベター・コール・ソール)を生み出しました。ウェントウのテキストとビデオは、劇中のソウル・グッドマンのテレビコマーシャルです。製品(サービス)、競争戦略、市場ポジショニング、ブランド名、ターゲット顧客グループ、コミュニケーション軸から広告まで、サル・グッドマンの役割のビジネス設定は、「最低」と見なすことができる超超超超超超完全です。ブランドコミュニケーションのコスト」「変化」のモデル。なぜ?私の分析をご覧ください。3.ソウル・グッドマンの「事業戦略」1.基本情報ブランド名:Saul Goodman製品:法律相談サービス対象顧客:麻薬中毒、飲酒運転、事故など。法律知識の欠如は、一般的に公立弁護士にしか余裕がなく、真面目な弁護士も「特別な法律を持つ消費者」を避けます。恐れてはいけない「ニーズ」。コミュニケーションの主軸:この国のすべての男性、女性、子供は有罪判決を受けるまで無実だと思います。地域:アルバカーキ市スローガン:Thrallに電話したほうがいいです!(ベター・コール・ソール)広告:2つの可能性のある犯罪状況をシミュレートします+サウルの主張+サウルのスローガン2をより適切に呼び出します。