拒否は連鎖した約束では伝播されない
P粉193307465
P粉193307465 2023-10-23 17:50:47
0
2
2865

なぜ拒否が Promise チェーンを通過しないのか理解できません。誰かがその理由を理解するのを手伝ってくれることを願っています。私にとって、関数を一連の Promise にアタッチするということは、元の Promise の意図が満たされることに依存していることを意味します。これを説明するのは難しいので、最初に私の問題のコード例を示します。 (注: この例では、Node と遅延ノード モジュールを使用します。Dojo 1.8.3 を使用してこれをテストしましたが、同じ結果が得られました)

リーリー

この操作を実行した結果は次の出力になります:

リーリー

そうですね、私にとって、この結果は意味がありません。この Promise チェーンに追加することにより、それぞれは、d1 の成功した解決とチェーンに沿って渡される結果に依存するという意図を暗示します。 Promise1 の Promise が wi​​ns 値を受け取らず、エラー ハンドラーで err 値を受け取った場合、チェーン内の次の Promise はどのようにして success 関数を呼び出すことができるでしょうか?値自体を取得できないため、次の Promise に意味のある値を渡すことはできません。

私のアイデアを別の方法で説明します。ジョン、ジンジャー、ボブの 3 人がいます。ジョンはウィジェット ストアを所有しています。ジンジャーさんは店に入り、さまざまな色のウィジェットが入った袋を求めました。在庫がなかったので、ディーラーに発送してもらうようリクエストを送りました。その間、彼はジンジャーに雨の小切手を渡し、彼女にウィジェットの入ったバッグの借りがあると言いました。ボブはジンジャーがウィジェットを入手しているのを見つけ、使い終わったら青いウィジェットを入手するように頼みます。彼女は同意し、同意する旨のメモを彼に渡しました。現在、ジョンのディーラーは供給品の中にウィジェットを見つけることができず、メーカーはもうウィジェットを製造していないため、ジョンに通知し、ジョンはジンジャーにウィジェットを入手できないことを通知します。ボブは自分では何も得られないのに、どうやってジンジャーから青いウィジェットを手に入れることができるでしょうか?

この問題に関する私の 3 番目の、より現実的な見解は次のとおりです。データベースに更新したい値が 2 つあるとします。 1 つはもう 1 つの ID に依存しますが、データベースに挿入して結果を取得するまで ID を取得できません。さらに、最初の挿入はデータベース クエリに依存します。データベース呼び出しによって返された Promise は、2 つの呼び出しをシーケンスに連鎖させるために使用します。

リーリー

この場合、db.query が失敗すると、最初の then の err 関数が呼び出されます。しかし、その後、次の Promise の success 関数が呼び出されます。この Promise は最初の値の結果を期待していますが、エラー処理関数からエラー メッセージを受け取ります。

それでは、私の質問は、success 関数でエラーをテストする必要がある場合、なぜエラー処理関数があるのか​​ということです。

申し訳ありませんが、この記事は長すぎます。別の方法で説明する方法がわかりません。

更新と修正

(注: いくつかのコメントに対する返信を削除しました。そのため、誰かが私の返信にコメントした場合、削除したため、そのコメントは文脈から外れて表示される可能性があります。申し訳ありませんが、そのままにしておこうとしました。できるだけ短くしてください。)

ご返信ありがとうございます。まず最初に、私の質問、特に疑似コードの書き方が非常に悪かったことを皆さんにお詫びしたいと思います。短くしようとして少し積極的になりすぎました。

ベルギさん、ご返信ありがとうございます。私のロジックに間違いがあったようです。私が抱えている問題の原因となっている別の問題を見落としているのではないかと思います。これにより、Promise チェーンが予想とは異なる動作をする可能性があります。まだコードのさまざまな要素をテストしているため、何が間違っているのかを確認するための適切な質問を作成することさえできません。しかし、状況については皆さんに最新の情報を伝えたかったので、ご協力に感謝いたします。

P粉193307465
P粉193307465

全員に返信(2)
P粉155710425

@Jordan まず、コメント投稿者が指摘したように、最初の例は、遅延ライブラリを使用したときに期待する結果を確実に生成します。 リーリー

第二に、提案した出力が生成されたとしても、2 番目のコード スニペットの実行フローには影響しません。これは少し異なり、次のようなものです。 リーリー

そして、最初の約束が拒否された場合、出力のみ:

リーリー

ただし (

最も興味深い部分に進みます

) 遅延ライブラリは間違いなく 3 x 戻り値 を返しますが、他のほとんどの Promise ライブラリは 1 x 戻り値、2 x を返します。解決済み (これにより、他の Promise ライブラリを使用してこれらの結果が得られると想定されます)。 また、他のライブラリがより正しく動作することも混乱を招きます。説明しましょう。

同期の世界では、「約束の拒否」に相当するのは

throws

です。したがって、意味的に言えば、同期の async deferred.reject(new Error())throw new Error() と同じです。 あなたの例では、同期コールバックでエラーをスローせず、エラーを返すだけなので、エラーが成功値である成功フローに切り替えます。それ以降のパスを確実に拒否するには、エラーを再スローする必要があります: リーリー ここで問題は、なぜ遅延ライブラリが返されたエラーを拒否として扱うのかということです。

その理由は、仕事が遅れた場合の拒否は少し異なるからです。 deferred lib のルールは次のとおりです。

エラーインスタンスが発生すると、Promise は拒否されます

したがって、 deferred.resolve(new Error()) を実行しても機能しますdeferred.reject(new Error()) と同様に、deferred.reject(notAnError) を実行しようとすると、Promise はエラーでのみ拒否できることを示す例外がスローされます。これは、then コールバックから返されたエラーが Promise を拒否する理由を明確に示しています。 defer ロジックの背後にはいくつかの正当な理由がありますが、JavaScript での

throw

の動作とはまだ一致していないため、この動作は defer の v0.7 リリースで変更される予定です。 短い要約:

混乱や予期せぬ結果を避けるために、適切な実践のルールに従ってください:

エラー インスタンスのある Promise は常に拒否します (同期世界のルールに従い、エラーではない値をスローすることは悪い習慣と考えられます)。
  1. エラーをスローして同期コールバックを拒否します (エラーを返しても拒否が保証されるわけではありません)。
  2. 上記に従うと、Deferred およびその他の一般的な Promise ライブラリで一貫した期待どおりの結果が得られます。
いいねを押す +0
P粉376738875

###いいえ。あなたが説明しているのはチェーンではなく、単にすべてのコールバックを

d1 にアタッチするだけです。ただし、then を使用して何かをリンクする場合、promise2 の結果は、promise1 の解決策と promise1 の解決策によって異なります。 そして コールバックがそれを処理します 。

ドキュメントには次のように記載されています:

.then メソッドは通常、Promises/A 仕様 (より厳密には Promises/A ) を参照します。これは、コールバック シェルによって返された Promise が Promise2 の解決に同化され、成功/エラー ハンドラーがない場合、対応する結果が Promise2 code> に直接渡されることを意味します。そのため、単に ハンドラーを省略します エラーを伝播します。

ただし、エラーが

handled の場合、結果の promise2 は修正されたとみなされ、その値で満たされます。これが発生したくない場合は、try-catch 句と同様に error を再スローする必要があります。あるいは、ハンドラーから (保留中の) 拒否された Promise を返すこともできます。 Dojo の拒否が何であるかはわかりませんが、: リーリー 彼にはそんなことはできないはずだ。エラー ハンドラーがなければ、彼はウィジェットが残っていないというメッセージしか認識しません ((ジョンから) ジンジャーから) しかし、ジンジャーがこの状況にエラー ハンドラーを設定した場合、ジョンまたは彼のディーラーに青いウィジェットが残っていない場合、彼女はボブに自分のキャビンからウィジェットを提供し、彼に緑色のウィジェットを与えるという彼女の約束はまだ果たせます。 エラー コールバックをメタに変換するには、次のようにハンドラーからエラーを返します。「ウィジェットが残っていない場合は、ウィジェットが残っていないというコメントを与えてください。これは必要なウィジェットと同じです。パーツは単に良いよ。」

...これは、エラーがそこで処理されたことを意味します。そうでない場合は、エラー コールバックを省略してください。ところで、成功コールバックは作成している Promise を

return

しないため、役に立たないように見えます。正しいものは次のとおりです:

リーリー

または、前のコールバックの結果値にアクセスするためにクロージャは必要ないため、次のような場合でも: リーリー

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート