2017-02-21 53 views
2

是否有任何使用redux-loop來處理複雜的ajax工作流的例子?官方回購非常簡約。從我能找到的一個例子(https://hackernoon.com/why-i-wrote-a-redux-async-outerware-277d450dba74#.2ocaloc58)看來,redux-loop與redux-thunk非常相似。複雜的redux循環示例?

這裏有複雜的Ajax的工作流程的一些例子:

  • 阿賈克斯Workflow1。用戶在結果表上選擇兩個不同的過濾器。每個過濾器都會啓動一個ajax請求,然後按順序排除。結果表格應顯示正確的過濾器選擇。錯誤不應該更新結果表。
  • Ajax的工作流程2
    • 用戶啓動一個報告生成(這是一種長時間運行的過程)。
    • 用戶切換到另一個報告。它應該取消或忽略待處理的「等待報告」操作。
  • 更復雜的工作流(基於舊終極版-佐賀示例)
    • 用戶按下登錄按鈕,它啓動一個AJAX請求來獲取令牌一個auth
    • 要麼
      • 用戶立即按下注銷按鈕,該按鈕應該取消/忽略掛起的認證動作
      • 或者它應該在解析時存儲認證令牌
    • 應該退出後清除身份驗證令牌或出現登錄錯誤

回答

2

我會給在第二個工作流(登錄)一杆。

在進入代碼之前,值得注意的是redux-loop比異步控制流程簡單很多,並且提供了小於redux-saga。但本着Elm的精神,重點在於數據流 - 通常通過數據類型來實現這一點並不令人意外。因此,從靜態類型語言的角度思考是有幫助的。在HaskellElm,這可能有利於模型的數據類型,其本身編碼狀態機的問題:

data LoginStatus data err = 
    LoggedOut  | 
    , LoggedIn data | 
    , LoginError err | 
    , Pending 

dataerr是類型變量代表登錄的數據類型(標記)和登錄錯誤。 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的不同變體。幾個例子指出:

{ 
    LoggedOut : true 
} 


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

{ 
    Pending : true 
} 

隨着該清理,這裏是在主減速器使用的子減速器:

// 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 }; 
} 

這些就像在有限狀態機轉變,除了有時與數據附屬於該州。每個單獨的reducer都相當簡單,並且處理很少的動作類型。只有兩個減速返回效果:

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

這種轉變從LoggedOut/LoginError狀態,以Pending並指定一些副作用 - 這將由redux-loop安排。你甚至可以將這兩個變體合併爲一個:{ LoggedOut : error | null },但是我覺得從長遠來看,單獨的LoginError狀態是有益的。

對於某些數據類型的概念,這個問題比第一次出現時更容易推理;你可以用減速機做同樣的事情,結構大致相同,只用redux-thunk

+0

我很欣賞這種迴應,但......這種方法的問題在於它混合了責任。異步工作流程+「正常」狀態。這導致複雜的減速器。在真正的項目中,這意味着您只是更容易創建脆弱的代碼。此外,您還沒有解決如何實際完成上述工作流程。 –

+0

感謝您的反饋。這是合理的批評。對於最後一點,我相信我主要解決了它的工作原理。那麼,因爲我今天有一些空閒時間,所以在這裏解釋了使用減速器佈局的一個實例。它有一個'redux-loop'和'redux-sage'實現,幾乎完全相同的reducer:[https://github.com/yiransheng/redux-login-examples](https://github.com/yiransheng/redux -login-examples) –

+0

什麼是好的是你明確枚舉類型的想法。不幸的是,正如他們在美國所說的那樣,「你正在擊敗一匹死馬。」另外,對於關注點的混合,您沒有專門處理異步性的API。因此,在現實世界的項目中,代碼變得非常非常複雜(和重複)。例如,您不處理「取消」情況。其次,FRP /傳奇在測試中勝出。你不需要嘲笑。 –