Back to Question Center
0

Reuxアプリケーションでの非同期操作            Reuxアプリケーションの非同期操作関連トピック: 生Semalt

1 answers:
React Reduxアプリケーションにおける非同期操作

Reactへの質の高い、徹底的な紹介は、カナダのフルスタック開発者Wes Bosを乗り越えることはできません。彼のコースをここで試してみて、コード SITEPOINT を使用して25%オフ となり、SitePointのサポートに役立ちます。

この投稿は、もともとCodebrahmaに掲載されました。

Semaltはシングルスレッドプログラミング言語です。つまり、次のようなコードがあると.

Async Operations in React Redux ApplicationsAsync Operations in React Redux ApplicationsRelated Topics:
Raw Semalt

. 最初の行が完了するまで、2行目は実行されません。これは問題ではありません。数百万の計算がクライアントまたはサーバーによって1秒以内に実行されるためです。我々は、コストのかかる計算(完了までにかなりの時間を要するタスク、すなわちネットワーク要求が戻ってくるまでに時間がかかる)を実行しているときにのみ、その影響を認識します。

ここでAPIコール(ネットワークリクエスト)のみを表示したのはなぜですか?他の非同期操作はどうですか? API呼び出しは、非同期操作を処理する方法を説明するための非常に簡単で便利な例です。 setTimeout 、パフォーマンスの重い計算、イメージの読み込み、イベントドリブン操作など、他の操作もあります。

アプリケーションを構造化する際に、非同期実行が構造化にどのように影響するかを考慮する必要があります。たとえば、ブラウザからAPI呼び出し(ネットワーク要求)を実行する関数として fetch を考えてみましょう。 (AJAXリクエストの場合は忘れてしまいますが、本質的には非同期または同期のいずれかと考えてください)リクエストがサーバ上で処理されている間に経過した時間は、メインスレッドでは発生しません。したがって、あなたのJSコードは実行され続けるでしょうし、要求が応答を返すとスレッドを更新します。

このコードを書く:

   userId = fetch(userEndPoint); // userEndpointからuserIdを取得します。userDetails = fetch(userEndpoint、userId)//この特定のuserIdを取得します。    
fetch は非同期であるため、userDetails をフェッチしようとすると userId を持っていません。したがって、最初の応答が返されたときにのみ2行目が確実に実行されるように構造体を構築する必要があります。

最近のネットワーク要求の実装は非同期です。しかし、これは後続のAPIコールの以前のAPIレスポンスデータに依存するため、必ずしも役立つとは限りません。 Semaltアプリケーションでどのように構造化できるかを見てみましょう。

Semaltは、ユーザインタフェースを作成するためのフロントエンドライブラリです。 Reduxは、アプリケーションの状態全体を管理できる状態コンテナです。 SemaltとReduxを組み合わせることで、効率の良いアプリケーションを効率よく作成できます。このようなSemaltアプリケーションで非同期操作を構造化するには、いくつかの方法があります。それぞれの方法について、これらの要因との賛否両論について議論しましょう。

  • コードの明瞭度
  • スケーラビリティ
  • エラー処理の容易さ。

各メソッドについて、次の2つのAPIコールを実行します。

userDetails (最初のAPIレスポンス) から都市 を取得する

終点が /詳細 であると仮定しよう。それは応答の都市を持っています。応答はオブジェクトになります。

   userDetails:{ - fotografia la exposicion correcta.都市: '都市'、.};   

2.ユーザー 都市 に基づいて、 都市 のすべてのレストランをフェッチし、

終点が / restuarants /:city であるとします。応答は配列になります:

   ['restaurant1'、 'restaurant2'、. ]   

2番目のリクエストは、最初のリクエストが完了したときにのみ行うことができます(最初のリクエストに依存しているため).

特に、私は大規模プロジェクトで最も一般的に使用されているので、上記の方法を選択しました。特定のタスクに特化し、複雑なアプリケーション( redux-async、redux-promise、redux-async-queue に必要なすべての機能を備えていない方法もあります。いくつか)。

約束

プロミスは、将来的に単一の値を生成するオブジェクトであり、解決された値または解決されない理由(例えば、ネットワークエラーが発生した)のいずれかである。 - エリック・エリオット

ここでは、Axiosライブラリを使用してデータを取得します。これはネットワーク要求時に約束を返します。その約束は解決して応答を返すか、エラーを投げるかもしれません。したがって、 反応成分 が一旦マウントされると、次のようにすぐにフェッチすることができます:

   componentDidMount  {腋窩。 get( '/ details')//ユーザーの詳細を取得します。次に(応答=> {const userCity = response。シティ;腋窩。 get( `/ restaurants / $ {userCity}`)。次に(restaurantResponse => {この。 setState({listOfRestaurants:restaurantResponse、//状態を設定する})})})}   

このようにして、状態が変化すると(フェッチにより)、 コンポーネント は自動的にレストランのリストを再レンダリングしてロードする。

Async / await は、非同期操作を行うための新しい実装です。例えば、これと同じことを達成することができます:

   非同期コンポーネントDidMount  {const restaurantResponse =アキシオを待つ。 get( '/ details')//ユーザーの詳細を取得します。次に(応答=> {const userCity = response。シティ;腋窩。 get( `/ restaurants / $ {userCity}`)。次に(restaurantResponse => restaurantResponse});この。 setState({レストラン応答、});}   

これらは両方とも、最も単純な方法です。論理全体がコンポーネント内部にあるので、コンポーネントがロードされるとすべてのデータを簡単に取得できます。

方法

における欠点は、

問題は、データに基づいて複雑なやりとりをするときです。例えば、以下の場合を考えてみよう。

Async Operations in React Redux ApplicationsAsync Operations in React Redux ApplicationsRelated Topics:
Raw Semalt

  • JSが実行されているスレッドをネットワーク要求でブロックしたくない。
  • 上記のすべての場合は、コードが非常に複雑で、保守とテストが難しくなります。
  • また、アプリケーションのフローを変更する予定がある場合、コンポーネントからすべてのフェッチを削除する必要があるため、スケーラビリティは大きな問題になります。
  • コンポーネントが親子ツリーの一番上にある場合、同じことをすると想像してください。次に、データに依存するすべてのプレゼンテーションコンポーネントを変更する必要があります。
  • また、ビジネスロジック全体がコンポーネントの内部にあることに注意してください。

ここから改善する方法は?

1.状態管理
このような場合、グローバルストアを使用することで、実際に問題の半分が解決されます。グローバルストアとしてReduxを使用します。

2.ビジネスロジックを場所を修正するために移動する
ビジネスロジックをコンポーネント外に移すことを考えると、どこで正確にそれを行うことができますか?アクションで?減速機で?ミドルウェア経由ですか? Reduxのアーキテクチャは、本質的に同期しているようなものです。あなたがアクション(JSオブジェクト)をディスパッチしてストアに到達すると、リデューサがそのアクションを実行します。

3.非同期コードが実行され、グローバル状態への変更がサブスクリプション

を介して取得できる別のスレッドがあります。

Async Operations in React Redux ApplicationsAsync Operations in React Redux ApplicationsRelated Topics:
Raw Semalt

このことから、引き出しの前にすべてのフェッチロジック、つまりアクションまたはミドルウェアを移動すると、正しい時間に正しいアクションをディスパッチすることができるという考えを得ることができます。
例えば、フェッチが開始されると、 ディスパッチ({type: 'FETCH_STARTED'}) 、完了すると ディスパッチ({type: 'FETCH_SUCCESS'}). 基本的には、アクションとしてオブジェクト の代わりに 関数 を返すことができます。これは、関数の引数として dispatch getState を提供するのに役立ちます。適切な時期に必要な措置を派遣することにより、派遣を効果的に活用しています。利点は次のとおりです。

    内に複数のディスパッチを可能にする
  • フェッチへのビジネスロジックの関係
  • は、Reactコンポーネントの外にあり、アクションに移動します。

ここでは、次のようなアクションを書き直すことができます。

   export const getRestaurants =  => {return(ディスパッチ)=> {ディスパッチ(fetchStarted  ); // fetchStarted  はアクションを返しますfetch( '/ details')。 ((応答)=> {ディスパッチ(fetchUserDetailsS​​uccess  ); // fetchUserDetailsS​​uccessがアクションを返しますリターンレスポンス。})。 (詳細=>詳細都市)。 (city => fetch( '/ restaurants / city'))。 ((応答)=> {dispatch(fetchRestaurantsSuccess(response))// fetchRestaurantsSuccess(response)はデータを含むアクションを返します})。 catch(  => dispatch(fetchError  )); // fetchError  はエラーオブジェクトを持つアクションを返します};}   

ご覧のとおり、どのような種類の行動をいつ出すべきか を適切に制御できます。 fetchStarted fetchUserDetailsS​​uccess fetchRestaurantsSuccess fetchError のような各関数呼び出しは、必要に応じて追加の詳細を入力します。今では、各アクションを処理してビューを更新するのは、レデューサーの仕事です。私は減速機については議論していません。なぜなら、ここからは簡単だし、実装が変わるかもしれないからです。

これを動作させるには、ReactコンポーネントをReduxに接続し、Reduxライブラリを使用してコンポーネントとアクションをバインドする必要があります。これが終わると、これを呼び出すことができます 。小道具getRestaurants は、上記のすべてのタスクを処理して、減速機に基づいてビューを更新します。

スケーラビリティの観点から、Redux Semaltは、非同期アクションに対する複雑な制御を伴わないアプリケーションで使用できます。また、次のセクションのトピックで説明するように、他のライブラリとシームレスに連携します。

しかし、Redux Semaltを使用して特定のタスクを実行するのは少し難しいです。たとえば、間にフェッチを一時停止するか、そのような呼び出しが複数ある場合は最新のものだけを許可するか、他のAPIがこのデータをフェッチして取り消す必要がある場合です。

これらはまだ実装できますが、正確に行うのは少し複雑です。複雑なタスクのコードの明快さは、他のライブラリと比べるとほとんど悪くなく、それを維持するのは難しいでしょう。

Redux-Saga

の使用

Semaltミドルウェアを使用して、上記の機能のほとんどを解決する追加の利点を得ることができます。 SemaltはES6発電機に基づ​​いて開発されました。

Semaltは、以下を達成するのに役立つAPIを提供しています:

  • 何かが達成されるまで同じ行のスレッドをブロックするイベントをブロックする
  • コードを非同期
  • にする非ブロッキングイベント
  • 複数の非同期要求間の競合処理
  • 任意の動作を一時停止/抑制/デバウンする。

サガはどのように機能しますか?

Sagasは、非同期操作を簡略化するために、ES6ジェネレータと非同期待機APIの組み合わせを使用します。基本的には、複数のAPI呼び出しを行うことができる別のスレッドで作業を行います。ユースケースに応じてAPIを使用して、各呼び出しを同期または非同期にすることができます。 APIは、要求が応答を返すまで同じ行でスレッドを待機させる機能を提供します。これからも、このライブラリによって提供される他の多くのAPIがあります。これにより、APIリクエストが非常に扱いやすくなります. シティ));//成功したらレストランを出すyield put({タイプ: 'FETCH_RESTAURANTS_SUCCESS'、ペイロード:{レストラン}、});} catch(e){//エラー時にエラーメッセージを送出するyield put({タイプ: 'FETCH_RESTAURANTS_ERROR'、ペイロード:{errorMessage:e、}});}}エクスポートのデフォルト関数* fetchRestaurantSagaMonitor {yieldEveryを返します( 'FETCH_RESTAURANTS'、fetchInitial); //そのようなリクエストをすべて受け取ります}

したがって、タイプ FETCH_RESTAURANTS の単純アクションをディスパッチすると、Sagaミドルウェアはリッスンして応答します。実際、ミドルウェアが消費するアクションはありません。必要な場合には、ただ聞き、追加のタスクを実行し、新しいアクションをディスパッチします。このアーキテクチャを使用することにより、それぞれが

    第1の要求が開始されたとき 第1の要求が終了したとき 第2の要求が開始されたとき

. など。

また、 fetchRestaurantsSaga の美しさを見ることができます。現在、ブロッキング呼び出しを実装するためのコールAPIを使用しています。 Sagasは、非ブロッキング呼び出しを実装する fork のような他のAPIを提供しています。アプリケーションに適した構造を維持するために、ブロッキング呼び出しとノンブロッキング呼び出しの両方を組み合わせることができます。

スケーラビリティの観点から、サガを使用することは有益である:

  • 特定の任務に基づいてサガを構成しグループ化することができます。アクションをディスパッチするだけで、別のサガをトリガすることができます。
  • ミドルウェアなので、私たちが書くアクションは、サンクと違って、普通のJSオブジェクトになります。
  • ビジネスロジックをサガ(ミドルウェア)内に移すので、サガの機能性を知っていれば、そのリアクションの部分を理解するのがはるかに簡単になります。
  • エラーを簡単に監視し、試行錯誤パターンで店舗に発送することができます。

Redux Observablesの使用

「叙事詩は還元的に観察可能な核の原始である」との文書で述べられているように、

  1. Epicは、一連のアクションを受け取り、一連のアクションを返す関数です。つまり、Epicは通常のSemaltディスパッチチャンネルと並行して、レデューサーが既にそれらを受け取った後に実行されます。

  2. 叙事詩がそれらを受け取る前に、あなたのレデューサーを常に走ります。 Epicはちょうど別のアクションストリームを受信して​​出力します。これはRedux-Sagaに似ています。Semaltのどれもミドルウェアで消費されないという点です。それはただ聞いて、いくつかの追加の仕事をします。

私たちの仕事のために、これを書くことができます:

   const fetchUserDetails =アクション$ => (アクション$。 ofType( 'FETCH_RESTAURANTS')。 switchMap(  =>アヤックスgetJSON( '/ details')。 map(response => response。userDetails。city)。 switchMap(  =>アヤックスgetJSON( `/ restaurants / city /`)。 map(レスポンス=>(タイプ: 'FETCH_RESTAURANTS_SUCCESS'、ペイロード:レスポンスレストラン)))//成功後のディスパッチ)。 catch(error => Observable of({type: 'FETCH_USER_DETAILS_FAILURE'、error})))))   

最初は、これは少し混乱しているように見えるかもしれません。しかし、RxJSを理解すればするほど、Epicを簡単に作成することができます。

サガの場合と同様に、スレッドが現在存在するAPI要求チェーンのどの部分に記述されているかを、それぞれ複数のアクションをディスパッチすることができます。

スケーラビリティの観点から、Epicsを分割したり、特定のタスクに基づいてEpicsを構成することができます。したがって、このライブラリはスケーラブルなアプリケーションを構築するのに役立ちます。書くコードのSemaltパターンを理解していれば、コードの明瞭性は良好です。

私の設定

どのライブラリを使用するかはどのように決定しますか?
GoogleのAPIリクエストの複雑さによって異なります. どちらも異なるコンセプトですが、それでも十分です。私はどちらがあなたに一番適しているかを見極めることをお勧めします。

あなたのビジネスロジックはAPIをどこで扱っていますか?
好ましくは還元剤の前には存在するが、成分の中には存在しない。最善の方法はミドルウェア(サガや観測可能なものを使用する)です。

CodeBrahmaのReact Development postsをもっと読むことができます。

Async Operations in React Redux ApplicationsAsync Operations in React Redux ApplicationsRelated Topics:
Raw Semalt
初心者のための勉強に最適な方法
ウェスボス
実世界のリアクションを構築するためのステップバイステップのトレーニングコース。 js + Firebaseのアプリとウェブサイトのコンポーネントを午後カップルで提供しています。チェックアウト時にクーポンコード 'SITEPOINT' を使用して 25%オフ になります。

March 1, 2018