
キーポイント
- JavaScriptの単一の読み取りの性質は、API呼び出しなどの非同期操作がUIを非ブロックするために重要であり、これらの操作の効率的な取り扱いがReact Reduxアプリケーションで重要であることを意味します。
- Redux Thunk、Redux-Saga、およびRedux-Observablesは、人気のあるReduxの非同期操作管理ミドルウェアであり、それぞれがアプリケーションの複雑さとニーズに基づいて異なる利点を提供します。
- Redux Thunkは、アクションの代わりに戻り機能を許可し、これらの機能の連続API呼び出しと関連するデータを処理できるようにすることにより、非同期アクション分布を簡素化します。
- Redux-SagaはES6ジェネレーターを活用して、レース条件の取り扱い、一時停止、操作のキャンセルなどの複雑なシナリオにより強力なソリューションを提供し、大規模なアプリケーションに適しています。
- Redux-ObservablesはRXJを活用して、アクションフローを介して副作用を管理する強力な方法を提供し、複雑なアプリケーションアーキテクチャにおける非同期操作に対する優れたスケーラビリティと制御を提供します。
この記事は、もともとCodebrahmaで公開されました。
JavaScriptは、単一の読み取りプログラミング言語です。つまり、次のコードを書くとき...

…2行目は、最初の行が実行された後にのみ実行されます。クライアントまたはサーバーは毎秒数百万の計算を実行するため、ほとんどの場合、これは問題になりません。費用のかかる計算を実行するときにのみこれらの効果に気付きます(完了するのにかなりの時間がかかるタスク - ネットワークリクエストは返すのに時間がかかります)。
ここにAPI呼び出し(ネットワークリクエスト)のみを表示しているのはなぜですか?他の非同期操作はどうですか? API呼び出しは、非同期操作を処理する方法を説明する非常にシンプルで便利な例です。 setTimeout()
、パフォーマンス集約型のコンピューティング、画像読み込み、イベント駆動型操作など、他の操作があります。
アプリケーションを構築するときは、非同期実行が構造にどのように影響するかを考慮する必要があります。たとえば、ブラウザからAPI呼び出し(ネットワーク要求)を実行する関数と考えてください。 (AJAX要求であるかどうかを無視してください。その動作を非同期または同期として扱うだけです。)サーバー上でリクエストが処理されたときに経過する時間はメインスレッドでは発生しません。したがって、JSコードは引き続き実行され、リクエストが応答を返すと、スレッドが更新されます。 fetch()
このコードを検討してください:
この場合、
userId = fetch(userEndPoint); // 从 userEndpoint 获取 userId
userDetails = fetch(userEndpoint, userId) // 为此特定 userId 获取数据。
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
は非同期であるため、
を取得しようとするとfetch()
はありません。したがって、最初の行が応答を返した後にのみ2行目が実行されるようにする方法でそれを構築する必要があります。 userDetails
最新のネットワークリクエストのほとんどは非同期です。ただし、以前のAPI応答データに依存しているため、これは常に機能するとは限りません。 Reactjs/Reduxアプリケーションで特別に構築する方法を見てみましょう。
Reactは、ユーザーインターフェイスを作成するためのフロントエンドライブラリです。 Reduxは、アプリケーションの状態全体を管理する状態容器です。 ReadとのReactを使用すると、効率的でスケーラブルなアプリケーションを作成できます。このようなReactアプリケーションでは、非同期操作を構築するいくつかの方法があります。各方法について、次の要因に関してその利点と短所について説明します。
code clarity-
スケーラビリティ-
エラーを処理しやすい-
各メソッドについて、これらの2つのAPI呼び出しを実行します:
1
エンドポイントがuserDetails
であると仮定します。応答に都市が含まれます。応答はオブジェクトになります:
2。
エンドポイントが/details
であると仮定します。応答は配列になります:
userId = fetch(userEndPoint); // 从 userEndpoint 获取 userId
userDetails = fetch(userEndpoint, userId) // 为此特定 userId 获取数据。
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
最初のリクエストが完了した後にのみ2番目のリクエストを行うことができることを忘れないでください(最初のリクエストに依存するため)。さまざまな方法を見てみましょう:
約束またはasync/async/async/async/async/async/wite <
Redux Thunk
を使用しています
redux-saga/restuarants/:city
を使用します
Redux Observablesを使用して
userDetails: {
…
city: 'city',
…
};
ログイン後にコピー
私は、大規模なプロジェクトで最も一般的に使用される方法であるため、上記の方法を具体的に選択しました。特定のタスクにより具体的である可能性のある他の方法があり、複雑なアプリケーションに必要なすべての機能を持っているわけではありません(例:
Redux-Async、Redux-Promise、Redux-async-Queue- )。
setState
約束-
- 約束は、将来のある時点で単一の値を生成する可能性のあるオブジェクトです。解析値または未解決の原因(たとえば、ネットワークエラーが発生しました)。 - エリック・エリオット
-
この例では、Axiosライブラリを使用してデータを取得します。これは、ネットワークリクエストを行うときに約束を返します。約束は、応答を解析して返したり、エラーを投げたりする場合があります。したがって、
Reactコンポーネントがマウントされたら、次のように直接入手できます。
このようにして、州が(買収により)変更されると、コンポーネントがレストランリストを自動的に再レンダリングしてロードします。
async/awaitは、非同期操作を実行するために使用できる新しい実装です。たとえば、同じ関数を次のように達成できます。
両方の方法が最も簡単です。ロジック全体がコンポーネント内にあるため、コンポーネントがロードされた後、すべてのデータを一度に簡単に取得できます。
この方法の欠点
複雑なデータベースの相互作用が発生すると問題が発生します。たとえば、次の状況を検討してください

- JSを実行するスレッドをネットワークリクエストによってブロックすることは望ましくありません。
- 上記のすべての状況により、コードは非常に複雑で維持とテストが困難になります。
また、アプリケーションのフローを変更する予定がある場合、コンポーネントからすべてのフェッチ操作を削除する必要があるため、スケーラビリティは大きな問題になります。 -
コンポーネントが親子の木の上にある場合に何をするか想像してみてください。次に、データに依存するすべての表現コンポーネントを変更する必要があります。 -
また、ビジネスロジック全体がコンポーネント内にあることにも注意してください。
-
どのように改善しますか?
グローバルストレージを使用したステータス管理は、実際にこれらのケースで問題の半分を解決できます。グローバルストレージとしてReduxを使用します。
-
ビジネスロジックを適切な場所に移動します。コンポーネントからビジネスロジックを移動することを検討した場合、これはどこでこれを行うことができますか?アクションで?還元剤で?ミドルウェアを通して? Reduxのアーキテクチャは同期しています。アクション(JSオブジェクト)を配布すると、ストレージに到達すると、還元剤が動作します。
-
非同期コードを実行する別のスレッドがあり、グローバル状態の変更はサブスクリプション によって取得できることを確認してください。
-
これから、還元剤、つまりアクションまたはミドルウェアの前にすべての取得ロジックを移動すると、正しいアクションを適切なタイミングで配布できることを知ることができます。たとえば、フェッチが起動したら、
を配布でき、それが完了したら
を配布できます。
React JSアプリケーションを開発したいですか? dispatch({ type: 'FETCH_STARTED' })
dispatch({ type: 'FETCH_SUCCESS' })
Redux Thunk
を使用しています
Redux Thunkは、Reduxのミドルウェアです。基本的に、オブジェクトの代わりにアクションとして関数を返すことができます。これは、関数のパラメーターとして
および
を提供することで役立ちます。必要なアクションを適切なタイミングで配布するために
を使用します。利点は次のとおりです
dispatch
関数内の複数の分布を許可しますgetState
dispatch
ビジネスロジックとの協会は、Reactコンポーネントからアクションに移動されます。
- 私たちの例では、次のようなアクションを書き直すことができます:
userId = fetch(userEndPoint); // 从 userEndpoint 获取 userId
userDetails = fetch(userEndpoint, userId) // 为此特定 userId 获取数据。
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ご覧のとおり、どのタイプのアクションが分散されているかを適切に制御できます。各関数呼び出し(fetchStarted()
、fetchUserDetailsSuccess()
、fetchRestaurantsSuccess()
、fetchError()
など)は、通常のJavaScriptオブジェクトのタイプのアクションを配布し、必要に応じて追加の詳細を追加できます。したがって、還元剤のタスクは、各アクションを処理し、ビューを更新することです。ここから簡単で、実装が異なる可能性があるため、Reducerについては説明しませんでした。
この作業を行うには、ReactコンポーネントをReduxに接続し、Reduxライブラリを使用してアクションをコンポーネントに結合する必要があります。完了したら、単にを呼び出すことができます。これにより、上記のすべてのタスクが処理され、還元剤に応じてビューを更新できます。 this.props.getRestaurants()
そのスケーラビリティのために、Reduxサンクは、非同期アクションの複雑な制御を伴わないアプリケーションに使用できます。さらに、次のセクションのトピックで説明されているように、他のライブラリとシームレスに動作します。
ただし、reduxサンクを使用して特定のタスクを実行することはまだ少し難しいです。たとえば、中間のフェッチ操作を一時停止するか、複数のそのような呼び出しがある場合のみ最新の通話を許可する必要があります。他のAPIがこのデータを取得してキャンセルする必要があります。
これらを実装できますが、正確に実行する方が複雑になります。他のライブラリと比較して、複雑なタスクのコードの明確さはわずかに悪化し、維持がより困難になります。
redux-saga
を使用します
Redux-Sagaミドルウェアを使用すると、上記の機能のほとんどに対処するための追加の利点を獲得できます。 Redux-Sagaは、ES6ジェネレーターに基づいて開発されています。
Redux-Sagaは、次の目標を達成するのに役立つAPIを提供します。
イベントのブロック、いくつかの操作が完了するまで同じ行でスレッドをブロックする
非ブロッキングイベント、コードを非同期にします
- 複数の非同期リクエスト間の競合を処理します
- 一時停止/スロットリング/アクションを解除する
-
佐賀はどのように働きますか? -
SAGAは、ES6ジェネレーターとASYNC/待望のAPIの組み合わせを使用して、非同期操作を簡素化します。基本的に、複数のAPI呼び出しを行うことができる個別のスレッドで作業を行います。 APIを使用して、ユースケースに応じて、各コールを同期または非同期にすることができます。 APIは、リクエストが応答を返すまで、スレッドを同じ行で待機させる機能を提供します。それとは別に、このライブラリは他の多くのAPIを提供し、APIリクエストを非常に簡単に処理できます。
したがって、タイプの単純なアクションを使用して配布すると、SAGAミドルウェアが聞き、応答します。実際、ミドルウェアではアクションは使用されていません。他のいくつかのタスクを聴いて実行するだけで、必要に応じて新しいアクションを配布します。このアーキテクチャを使用することにより、複数のリクエストを配布できます。それぞれが説明します。
- 最初のリクエストはいつ開始されますか?
- 最初のリクエストがいつ完了するのか
2番目のリクエストはいつ開始されますか?-
など。
さらに、
の利点を見ることができます。現在、ブロッキングコールを実装するために APIを使用しています。 SAGAは、非ブロッキングコールを実装するfetchRestaurantSaga()
などの他のAPIを提供します。ブロッキングと非ブロッキングコールを組み合わせて、アプリケーションに適した構造を維持できます。 call
スケーラビリティを使用すると、SAGAを使用することが有益です:fork()
特定のタスクに基づいてSAGAを構築およびグループ化できます。単にアクションを配布することで、別のサガからサガをトリガーできます。
それはミドルウェアであるため、私たちが書いたアクションは、サンクとは異なり、通常のJSオブジェクトになります。 -
ビジネスロジックをSAGA(ミドルウェア)内に配置しているため、SAGAが何ができるかを知っていれば、その反応部分を理解する方がはるかに簡単です。 -
エラーは簡単に監視し、Try/Catchモードを介してストレージに配布できます。 -
- redux-observablesを使用
そのドキュメントで述べたように、「叙事詩はredux-bservableのコアプリミティブです」セクション:
叙事詩は、アクションストリームを受信し、アクションストリームを返す関数です。つまり、エピックは、還元剤がそれらを受信した後、通常のRedux配布チャネルと並行して実行されます。
アクションは、Epicがそれらを受信する前に、常に還元剤を介して実行されます。 Epicは、別のアクションストリームのみを受信および出力します。これは、Middlewareで使用されていないため、Redux-Sagaに似ています。他のいくつかのタスクを聴いて実行するだけです。 -
- 私たちのタスクについては、次のコードを簡単に記述できます。
最初は、これは少し混乱するように思えるかもしれません。ただし、RXJSを理解すればするほど、叙事詩を作成しやすくなります。
SAGAと同様に、複数のアクションを配布できます。各アクションは、スレッドが現在入っているAPIリクエストチェーンのどの部分を説明しています。 userId = fetch(userEndPoint); // 从 userEndpoint 获取 userId
userDetails = fetch(userEndpoint, userId) // 为此特定 userId 获取数据。
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
スケーラビリティの観点から、特定のタスクに基づいて叙事詩を分割または組み合わせることができます。したがって、このライブラリは、スケーラブルなアプリケーションの構築に役立ちます。執筆コードの観察可能なパターンを理解すれば、コードの明確さは良好です。
私の好み
使用するライブラリを決定する方法は?これは、APIリクエストの複雑さによって異なります。
Redux-SagaとRedux-Observableのどちらかを選択するにはどうすればよいですか?学習ジェネレーターまたはRXJに依存します。どちらも異なる概念ですが、同様に十分です。どちらがあなたの方が良いかを両方にしようとすることをお勧めします。
APIを処理するためのビジネスロジックはどこに置かれていますか?レデューサーの前に置くのが最善ですが、コンポーネントには入れるのが最善です。最良の方法は、ミドルウェア(SAGAまたはOBSERVABLEを使用)にあります。
CodeBrahmaのReact Development Articleをもっと読むことができます。
React-Reduxアプリケーションにおける非同期操作に関する
FAQ
Reduxでの非同期操作の処理におけるミドルウェアの役割は何ですか?
Reduxのミドルウェアは、非同期操作の処理において重要な役割を果たします。分布アクションとアクションの間にサードパーティの拡張ポイントを提供し、還元剤に到着します。ミドルウェアは、アクションを記録、変更、さらにはキャンセルし、他のアクションを配布するために使用できます。非同期操作のコンテキストでは、Redux ThunkやRedux Sagaなどのミドルウェアを使用すると、アクションの代わりに機能を返すアクションクリエイターを作成できます。この関数を使用して、アクションの分布を遅らせるか、特定の条件が満たされた場合にのみアクションを分配することができます。
Redux Thunkは非同期操作の管理にどのように役立ちますか?
Redux Thunkは、アクションの代わりに関数を返すアクションクリエーターを作成できるミドルウェアです。サンクを使用して、アクションの分布を遅らせたり、特定の条件が満たされた場合にのみアクションを配布することができます。この機能により、Reduxで非同期操作を処理するための優れたツールになります。たとえば、アクションを配布してAPI呼び出しの開始を示し、コールがデータまたはエラーメッセージを返すときに別のアクションを配布できます。
ReduxサンクとRedux Sagaの違いは何ですか?
Redux ThunkとRedux Sagaはどちらも、非同期操作を含むReduxの副作用を管理するためのミドルウェアです。 2つの主な違いは、そのアプローチです。 Redux Thunkはコールバック関数を使用して非同期操作を処理しますが、Redux Sagaは発電機関数とより宣言的な方法を使用します。これにより、Redux Sagaはより強力で柔軟になりますが、より複雑になります。アプリケーションに単純な非同期操作がある場合、Redux Thunkで十分です。ただし、人種条件、キャンセル、およびIF-ELSEロジックを含むより複雑なシナリオの場合、Redux Sagaがより良い選択かもしれません。
Reduxの非同期操作でエラーを処理する方法は?
非同期操作中にエラーが発生したときにアクションを配布できます。このアクションは、ペイロードとしてエラーメッセージを実行できます。その後、このアクションを還元剤で処理して、エラーメッセージでステータスを更新できます。このようにして、ユーザーにエラーメッセージを表示するか、デバッグのために記録することができます。
reduxで非同期アクションをテストする方法は?
Reduxの非同期アクションは、ReduxストレージとAPI呼び出しをモッキングすることでテストできます。 Reduxストレージの場合、
などのライブラリを使用できます。 API呼び出しでは、やredux-mock-store
などのライブラリを使用できます。テストでは、非同期アクションを分配し、予想されるアクションが正しいペイロードで配布されていることを主張できます。 fetch-mock
nock
Reduxで非同期操作をキャンセルする方法は?
Redux Sagaのようなミドルウェアを使用して、Reduxでの非同期操作をキャンセルできます。 Redux Sagaは発電機関数を使用します。これは、効果を使用してキャンセルできます。
効果が得られると、SAGAは現在の効果がキャンセルされるまで、スタートアップポイントからキャンセルされます。
Reduxの非同期操作で人種条件を処理する方法は?
Redux Sagaのようなミドルウェアを使用して、Reduxの非同期操作で人種条件を処理できます。 Redux Sagaは、同時アクションを処理するために使用できるやtakeLatest
などの効果を提供します。たとえば、以前に開始されたSAGAタスクがまだ新しいアクションが分散されているときに実行されている場合、takeEvery
タスクをキャンセルします。 takeLatest
async/async/await with asyncを使用する方法は?
Redux Thunkは、ネイティブにAsync/awaitをサポートします。アクションクリエーターでは、通常の機能の代わりに非同期関数を返すことができます。この非同期関数の内部では、非同期操作を処理するためにAsync/待ち望を使用できます。非同期操作が完了すると、アクションオブジェクトを使用して関数を呼び出すことができます。 dispatch
非同期操作での荷重状態をreduxで処理する方法は?
非同期操作における非同期操作における負荷状態は、非同期操作の前後にアクションを分配することで処理できます。操作前に配布されたアクションは、負荷ステータスをtrueに設定でき、操作後に配布されるアクションはfalseに設定できます。レデューサーでは、これらのアクションを処理して、ストレージ内の負荷状態を更新できます。
reduxの副作用に対処する方法は?
Reduxの副作用は、Redux ThunkやRedux Sagaなどのミドルウェアを使用して処理できます。これらのミドルウェアを使用すると、アクションの代わりに関数を返すアクション作成者を作成できます。この関数は、非同期操作、ロギング、条件付き分散アクションなどの副作用を実行するために使用できます。
以上がReact Reduxアプリケーションの非同期操作の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。