2017-02-21 2 views
2

redux-loopを使用して複雑なAjaxワークフローを処理する例はありますか?公式レポは非常にミニマルです。野生の一例から、(https://hackernoon.com/why-i-wrote-a-redux-async-outerware-277d450dba74#.2ocaloc58)を見つけることができました。それはredux-loopがredux-thunkと非常に似ているようです。複雑なreduxループの例?

  • アヤックスWorkflow1:ここ

    は、複雑なAjaxのワークフローの例をいくつか示します。ユーザーは結果表で2つの異なるフィルターを選択します。各フィルタはajaxリクエストを開始し、順番通りに解決します。結果テーブルに正しいフィルタ選択が表示されます。エラーは結果テーブルを更新すべきではありません。

  • Ajaxのワークフロー2
    • ユーザーは、(長い実行中のプロセスである)レポートの生成を開始します。
    • ユーザーは別のレポートに切り替えます。保留中の「レポート待ち」アクションを取り消すか、無視する必要があります。 (旧Reduxの-佐賀例に基づいて)
  • より複雑なワークフロー
    • ユーザープレスログインボタン、
    • どちらか
        トークン認証を取得するためのAJAXリクエストを開始します
      • すぐにユーザがログアウトボタンを押すと、保留中の認証アクションをキャンセル/無視する必要があります。
      • または解決するときに認証トークンを保存する必要があります。
    • ログアウト後に認証トークンをクリアする必要がありますか、ログインエラーが

答えて

2

を発生した場合、私は2番目のワークフロー(ログイン)で打撃を与えるだろう。

コードに入る前に、redux-loopは、よりシンプルであり、非同期制御の流れに関してredux-sagaよりも少ないことに注意してください。しかし、Elmの精神で、データフローに重点が置かれています。したがって、静的に型指定された言語の観点から考えることは有益です。 HaskellまたはElmでは、それはおそらく自体は、ステートマシンをエンコードするデータの種類によって問題をモデル化することが有益だ:

dataerrは型変数です
data LoginStatus data err = 
    LoggedOut  | 
    , LoggedIn data | 
    , LoginError err | 
    , Pending 

は、ログインデータ型(トークン)とログインエラーを表します。動的に型定義されたJavaScriptには、同じ考えを表現する利点はありませんが、LoginStatusのようなタグ付きユニオンタイプを模倣するために使用できるダイナミックな技がたくさんあります。ここで

import {match} from "single-key"; 

export default function reducer(state, action) { 
    return match(state, { 
    LoggedOut :() => loggedOutReducer(state, action), 
    LoggedIn :() => loggedInReducer(state, action), 
    Pending :() => pendingReducer(state, action), 
    LoginError :() => loginErrorReducer(state, action) 
    }); 
} 

は、私は非常に基本的なランタイム共用体型を達成するために、シンプルであまり知られていないライブラリsinge-keyを使用します。さらに前がなければ、ここのコードです。名前が示す「単一キー」オブジェクトは、{ a: 1 }(「a」がキー、1が値)など、キーと値だけを持つオブジェクトです。単一キーオブジェクトを使用して状態をモデル化します。異なるキーはLoginStatusの異なるバリアントを表します。いくつかの例では、状態:これらは時々のデータを除いて、有限状態マシンの遷移のようなもの

// state :: { LoggedIn: {/* some data * } } 
function loggedInReducer(state, action) { 
    if (action.type === LOGOUT) { 
    return { 
     LoggedOut : true 
    }; 
    } 
    return state; 
} 
// state :: { Pending : true } 
function pendingReducer(state, action) { 
    if (action.type === LOGIN_SUCCESS) { 
    return { 
     LoggedIn : { 
     token : action.payload.token, 
     user : action.payload.user 
     } 
    }; 
    } 
    if (action.type === LOGIN_ERROR) { 
    return { 
     LoginError : action.payload; 
    }; 
    } 
    if (action.type === LOGOUT) { 
    return { 
     LoggedOut : true 
    }; 
    } 
    return state; 
} 
// state :: { LoggedOut : true } 
function loggedOutReducer(state, action) { 
    if (action.type === LOGIN) { 
    return loop({ Pending: true }, Effects.promise(loginRequest)); 
    } 
    return state; 
} 
// state :: { LoginError : error } 
function loginErrorReducer(state, action) { 
    if (action.type === LOGIN) { 
    return loop({ Pending: true }, Effects.promise(loginRequest)); 
    } 
    return { LoggedOut : true }; 
} 

:片付けことで

{ 
    LoggedOut : true 
} 


{ 
    LoggedIn : { 
    token : 1235, 
    user : { firstName: "John" } 
    } 
} 

{ 
    Pending : true 
} 

が、ここでの主な減速に使用されるサブ減速しています状態に付いている。個々のレデューサーはかなりシンプルで、アクションタイプはほとんどありません。 - redux-loopによってスケジュールされます。これは、PendingLoggedOut/LoginErrorからの状態を遷移し、いくつかの副作用を指定

return loop({ Pending: true }, Effects.promise(loginRequest)); 

:2つだけ減速が影響を返します。あなたは2つのバリアントを1つに統合することもできます:{ LoggedOut : error | null }しかし、私は別々の状態を持っていると感じます。長期的には有益な状態です。

データ型の概念によっては、この問題は最初に現れるよりも簡単に判断することができます。あなたは同じものを同じように構成することができます減速器はほぼ同じ構造とredux-thunkを使用して構造化されています。

+0

私はこの回答に感謝しますが、このアプローチの問題は、それが責任を混同していることです。非同期ワークフロー+「通常の」状態。これは複雑な減速器につながる。実際のプロジェクトでは、脆弱なコードを簡単に作成できるようになりました。また、上記のワークフローを実際に実行する方法についても説明していません。 –

+0

フィードバックいただきありがとうございます。これは妥当な批判です。最後の点については、私はそれがどのように機能するかについて主に取り組んできたと信じています。さて、私は今日、いくつかの自由時間があるので、ここで説明した減速機のレイアウトを使った実例を作っただけです。これは、ほぼ同一のレデューサーを持つ 'redux-loop'と' redux-sage'の両方の実装を持っています:[https://github.com/yiransheng/redux-login-examples](https://github.com/yiransheng/redux -login-examples) –

+0

明示的に型を列挙するのは良い考えです。残念なことに、彼らがアメリカで言うように、 "あなたは死んだ馬を打っています。"さらに、懸案事項の混在には、非同期性を扱うための専用APIはありません。したがって、現実の世界のプロジェクトでは、コードは非常に複雑になります(繰り返します)。たとえば、「キャンセル」の場合は処理しません。第二に、FRP /サガはテストで勝つ。モックは必要ありません。 –