RxJS:将第一个源排队,直到第二个源遇到谓词

时间:2017-11-09 21:28:35

标签: javascript reactjs rxjs react-redux redux-observable

如何使用RxJS实现此方案。

当我想要获取用户(第一个来源)时,我需要检查互联网连接(第二个来源)。如果未连接互联网,请将第一个源排队,直到互联网重新开启。如果互联网重新开启,则发出第一​​个来源。我可以制作后一个,但我无法理解如何排队第一个源,直到第二个源为真。

请在此处查看我的代码:

const userEpic = action$ =>
  action$.ofType(USER_REQUEST)
    .withLatestFrom(action$.ofType(CONNECTION))
    .filter(([first, second]) => second.value === true)
    .do(a => console.log('can fetch a user'))    
    .mapTo({ type: SUCCESS });

http://jsbin.com/zomikukiqi/1/edit?js,console,output

1 个答案:

答案 0 :(得分:0)

尝试buffer()存储USER_REQUEST,直到CONNECTION触发缓冲区刷新。



const USER_REQUEST = 'USER_REQUEST';
const CONNECTION = 'CONNECTION';
const SUCCESS = 'SUCCESS';

const requestUser = () => ({ type: USER_REQUEST });
const connection = (x) => ({ type: CONNECTION, value: x });

const bufferedUserRequests$ = (action$, store) =>
  action$.ofType(USER_REQUEST)
    .filter(x => !store.getState().connectionStatus)    
    .buffer(action$.ofType(CONNECTION))

const unbufferedUserRequests$ = (action$, store) =>
  action$.ofType(USER_REQUEST)
    .filter(x => store.getState().connectionStatus)    
    .map(request => [request])

const userEpic = (action$, store) =>
   Rx.Observable.merge(
     bufferedUserRequests$(action$, store), 
     unbufferedUserRequests$(action$, store)
   )
   .flatMap(bufferArray => 
     bufferArray.map(request => Rx.Observable.of(request))
   )
   .do(a => console.log('can fetch a user'))
   .mapTo({ type: SUCCESS })

const reducer = (state = { connectionStatus: false}, action) => {
  switch (action.type) {
    case CONNECTION:
      return { ...state, connectionStatus: action.value }
    default:
      return state;
  }
};

// components/App.js

const { connect } = ReactRedux;

let App = ({ requestUser, connection, connectionStatus }) => (
  <div>
    <button onClick={requestUser}>Start Request</button>
    <p>Internet Connection: {connectionStatus.toString()}</p>
    <button onClick={() => connection(false)}>Disconnect</button>
    <button onClick={() => connection(true)}>Connect</button>
  </div>
);

App = connect(
  ({ connectionStatus }) => ({ connectionStatus }),
  { requestUser, connection }
)(App);

// redux/configureStore.js

const { Provider } = ReactRedux;
const { createStore, applyMiddleware } = Redux;
const { createEpicMiddleware } = ReduxObservable;

const epicMiddleware = createEpicMiddleware(userEpic);

const store = createStore(reducer,
  applyMiddleware(epicMiddleware)
);

// index.js

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
&#13;
<script src="https://unpkg.com/react@15.2.1/dist/react.min.js"></script>
<script src="https://unpkg.com/react-dom@15.2.1/dist/react-dom.min.js"></script>
<script src="https://unpkg.com/redux@^3.5.2/dist/redux.min.js"></script>
<script src="https://unpkg.com/react-redux@4.4.5/dist/react-redux.min.js"></script>
<script src="https://unpkg.com/@reactivex/rxjs/dist/global/Rx.js"></script>
<script src="https://unpkg.com/redux-observable/dist/redux-observable.min.js"></script>
  <div id="root"></div>
&#13;
&#13;
&#13;