2015-04-26 62 views
4

關於如何與Flux中的外部服務進行通信,有plentydiscussionFlux中應該在哪裏啓動HTTP請求?

很明顯,基本工作流是激發一個HTTP請求,最終根據響應調度成功或失敗的動作。在發出請求之前,您還可以選擇派遣「進行中」操作。

但是如果請求的參數取決於商店的狀態呢?似乎沒有人提及它。

所以基本上,基於用戶與視圖的交互,ACTION被調度。商店擁有關於如何從給定ACTION的當前狀態0轉換到下一個狀態1的邏輯。需要state1的數據才能正確形成新的HTTP請求。

例如,用戶在頁面上選擇一個新的過濾器,並且存儲決定也重置分頁。這應該導致一個新的HTTP請求(新的過濾值,第一頁),而不是(新的過濾值,來自狀態0的當前頁面)。

查看不能使HTTP調用本身正確與用戶的交互,因爲它然後將不得不復制商店的邏輯轉變到下一個狀態。

視圖無法在其store的onChange處理程序中進行HTTP調用,因爲此時不再知道狀態更改的起源是什麼。

它看起來像一個可行的選項,使存儲觸發動作處理程序中的HTTP請求,在它轉換到下一個狀態之後。但是這會使這個動作隱式地啓動HTTP調用,這會禁用完全可能性,以便具有用於調試的可重放日誌。

應該在Flux中啓動HTTP請求的位置?

回答

1

讓我們在底部開始:

它看起來像一個可行的選項,以使店火在動作處理HTTP請求,之後過渡到下一個狀態。但是這會使這個動作隱式地啓動HTTP調用,這會禁用完全可能性,以便具有用於調試的可重放日誌。

如果您處於調試/重放模式,則可以通過不啓動HTTP請求來緩解此問題。只要您在HTTP請求處理程序中執行的唯一的一件事是激發操作(例如SUCCESSFAILURE操作),此工作將非常有效。你可以用一個簡單的全局布爾值(if (!debug) { httpReq(...) })來實現這個,但是你也可以讓這個模式更正式。

Event Sourcing的說法中,您使用Gateways出於此目的。在正常操作中,網關發出HTTP請求,並在調試時關閉網關(因此它不發出任何HTTP請求)。

這就是說,我認爲這個問題實際上可以通過重新考慮你的HTTP請求的位置來解決。

因此,基本上,基於用戶與視圖的交互,ACTION被調度。商店擁有關於如何從給定ACTION的當前狀態0轉換到下一個狀態1的邏輯。需要state1的數據才能正確形成新的HTTP請求。

在你的問題(Where should ajax request be made in Flux app?),I recommend第二環節做你寫在行動創造者,但讀取商店。如果推斷該模式爲你的使用情況,你可能最終得到這樣的(僞代碼和長變量名的清晰度):

class DataTable extends React.Component { 
    render() { 
    // Assuming that the store for the data table contains two sets of data: 
    // one for the filter selection and one for the pagination. 
    // I'll assume they're passed as props here; this also assumes that 
    // this component is somehow re-rendered when the store changes. 
    var filter = this.props.filter; 
    var start = this.props.start; 
    var end = this.props.end; 

    var data = this.props.dataTableStore.getDataForPageAndFilter(
     start, end, filter 
    ); 

    // the store will either give us the LOADING_TOKEN, 
    // which indicates that the data is still loading, 
    // or it will give us the loaded data 
    if (data === DataTableStore.LOADING_TOKEN) { 
     return this.renderLoading(); 
    } else { 
     return this.renderData(data); 
    } 
    } 
} 

class DataTableStore { 
    constructor() { 
    this.cache = {}; 
    this.filter = null; 
    this.start = 0; 
    this.end = 10; 
    } 

    getDataForPageAndFilter(start, end, filter) { 
    var url = HttpApiGateway.urlForPageAndFilter(start, end, filter); 

    // in a better implementation, the HttpApiGateway 
    // might do the caching automatically, rather than 
    // making the store keep the cache 
    if (!this.cache[url]) { 
     this.cache[url] = DataTableStore.LOADING_TOKEN; 

     HttpApiGateway.query(url) 
     .then((response) => { 
     // success 
     var payload = { 
      url: url, 
      data: response.body 
     }; 
     dispatch(DATA_FETCH_SUCCESS, payload); 
     }, (error) => { 
     // error 
     dispatch(DATA_FETCH_FAIL, { ... }); 
     }); 
    } 

    return this.cache[url]; 
    } 

    handleChangeFilterAction(action) { 
    this.filter = action.payload.filter; 
    // the store also decides to reset pagination 
    this.start = 0; 
    this.end = 10; 
    this.emit("change"); 
    } 

    handleDataFetchSuccessAction(action) { 
    this.cache[action.payload.url] = data; 
    this.emit("change"); 
    } 

    handleDataFetchFailAction(action) { 
    // ... 
    } 
} 

DataTableStore.LOADING_TOKEN = "LOADING"; // some unique value; Symbols work well 

你可以看到,店裏負責決定如何更新分頁和過濾器變量,但不負責決定何時發出HTTP請求。相反,該視圖只是請求一些數據,並且如果商店沒有在緩存中,它將,然後發出HTTP請求。

這也允許視圖將任何其他本地狀態傳入getter(在HTTP請求也取決於本地狀態的情況下)。

0

我不確定要了解問題的所有部分,但會嘗試回答一些有用的見解。


Flux是有點像一個尚未成熟的版本EventSourcing/CQRS /領域驅動,設計前端開發

我們使用多年的一些類似於流量對後端用不同的術語。我們可以比較Flux ActionCreators與DDD命令Flux Actions to DDD Events

A 命令表示用戶意圖(LOAD_TIMELINE(過濾器))。它可以被命令處理程序接受或拒絕,最終會發布一些事件。在UI這並沒有太大的SENS拒絕命令,你不希望顯示用戶不應該點擊按鈕...

事件代表的東西,一直髮生在過去( )。

驅動UI的React應用程序狀態然後以某種方式將事件日誌投影到json狀態。如果沒有首先觸發事件,則任何事情都不能在UI上顯示。


回答你的問題

但是,如果請求的參數是什麼取決於商店的狀態呢?沒有人提到它,似乎 。

在DDD中,命令處理程序實際上可以是有狀態的。他們可以使用應用程序狀態來了解如何正確處理命令。不知怎的,這意味着你的流量ActionBuilders可以是有狀態太(也許他們可以使用一些存儲數據的同時)

所以基本上,基於與視圖的用戶交互,動作是 出動。商店擁有關於如何從當前狀態0 轉換到給定ACTION的下一個狀態1的邏輯。來自state1的數據需要 正確形成新的HTTP請求。

在DDD中有一個叫做Saga(或過程管理器)的概念。 爲了簡單起見,它接收事件流並可以產生新的命令。

所以基本上你可以通過佐賀表達你的要求:當有一個事件「FILTERS_UPDATED」時,用新的過濾器發出一個命令「RELOAD_LIST」。我很肯定你可以在任何Flux實現中實現類似的東西。

當您重放事件日誌時,薩達斯應該被禁用,因爲重放事件日誌不應該有像觸發新事件那樣的副作用。


這些類型的語義在我Atom-React框架,其中門店可以充當有狀態的命令處理程序或傳奇的支持。