Flux:waitFor特定事件

时间:2015-09-12 10:06:36

标签: javascript reactjs reactjs-flux flux

我试图了解如何解决商店之间的依赖关系。问题是我有一个全面的数据树,需要从服务器获取一个相互依赖的请求链。

问题: waitFor接缝不应该用于异步请求。假设下一个事件链:

  1. NEED_A(查看StoreA
  2. NEED_B(查看StoreB)此处StoreB执行AppDispatcher.waitFor([StoreA.dispatchToken])。但实际上我们想要等待GET_A
  3. SOME_OTHER_ACTION(查看StoreA
  4. waitFor调用StoreA.dispatchToken以来的第二步,第三步中断了SOME_OTHER_ACTION

    问题: 等待某些特定操作(GET_A)的真实方式是什么?

    让我们来看看代码(请注意三条PROBLEM条评论):

    StoreA

    var a = [];
    
    var StoreA = assign({}, EventEmitter.prototype, {
    
       getAProps: () => copyOfAProps(a);
    
       asyncGetA: () => ... //Async request returns Promise
    });
    
    StoreA.dispatchToken = AppDispatcher.register((action) => {
    
      switch(action.type) {
         NEED_A:
           StoreA.asyncGetA().then((data) => {             
             ActionCreator.getA(data); //Dispatches GET_A event
           });
           break;
         GET_A: 
           a = action.data;
           StoreA.emitChange();
         SOME_OTHER_ACTION: 
           //do whatever
      }
    
    });
    

    StoreB

    var b = [];
    
    var StoreB = assign({}, EventEmitter.prototype, {
    
       // PROBLEM: this request depends on data fetched from StoreA.asyncGetA
       asyncGetB: (A) => ...
    });
    
    StoreB.dispatchToken = AppDispatcher.register((action) => {
    
      switch(action.type) {
        //PROBLEM: NEED_B may happen before GET_A
        NEED_B:
          //PROBLEM: As I understand waitFor doesn't work here
          AppDispatcher.waitFor([StoreA.dispatchToken]);
          StoreB.asyncGetB(StoreA.getAProps()).then((data) => {
            ActionCreator.getB(data);
          });
        GET_B:
          b = action.data;
          StoreB.emitChange();
      }
    });
    

1 个答案:

答案 0 :(得分:3)

以下是来自https://github.com/calitek/ReactPatterns React.13 / ReFluxWebSocket的示例。 App.js触发Api.Store对ws.api.js执行的操作。 然后ws.api.js触发Api.Store作出反应的另一个动作。 这是一系列行动的例子。

这是Api.Store.js

    import Reflux from 'reflux';

    import Actions from './Actions';
    import ApiFct from './../utils/ws.api.js';

    function _apiInit() { ApiFct.init(); }
    function _apiInitDone() { ApiFct.getData(); }
    function _apiSetData(data) { ApiFct.setData(data); }

    var ApiStoreObject = {
        listenables: Actions,
        apiInit: _apiInit,
        apiInitDone: _apiInitDone,
        apiSetData: _apiSetData
    }
    const ApiStore = Reflux.createStore(ApiStoreObject);
    export default ApiStore;

这是ws.api.js

    import Actions from '../flux/Actions';

    module.exports = {
        socket: {},
        init: function() {
            this.socket = new Primus();
            this.socket.on('server:GotData', this.gotData);
            Actions.apiInitDone();
        },
        getData: function() { this.socket.send('client:GetData', {}); },
        gotData: function(data) { Actions.gotData(data); Actions.gotData2(data); },
        setData: function(data) { this.socket.send('client:SetData', data); },
    };

这是Actions.js

    import Reflux from 'reflux';

    var apiActions = [
        'apiInit',
        'apiInitDone',
        'apiSetData'
    ]

    var wsActions = [
        'gotData',
        'gotData2'
    ]

    var actionArray = wsActions.concat(apiActions);
    module.exports = Reflux.createActions(actionArray);

这是app.js

    'use strict';

    import React  from 'react';

    import AppCtrl from './components/app.ctrl.js';
    import Actions from './flux/Actions';
    import ApiStore from './flux/Api.Store';

    window.React = React;

    Actions.apiInit();

    React.render( <AppCtrl />, document.getElementById('react') );