【问题标题】:How to loop epic call如何循环史诗般的通话
【发布时间】:2019-03-01 08:32:17
【问题描述】:

我有以下史诗:

import {
  map,
  catchError,
  switchMap,
  takeUntil,
} from 'rxjs/operators';
import {
  FETCH_JOKES,
  jokesReceived,
  FETCH_JOKES_CANCELLED,
  jokesFetchFailed,
} from '../actions/jokes-action';
import { ofType } from 'redux-observable';
import { of, concat } from 'rxjs';
import { ajax } from 'rxjs/ajax';

const getJokes = () =>
  ajax.getJSON('http://api.icndb.com/jokes/random?escape=javascript');

const fetchJokesEpic = action$ => {
  return action$.pipe(
    ofType(FETCH_JOKES),
    switchMap(() =>
      getJokes().pipe(
        map(response => jokesReceived(response)),
        catchError((err, act) => of(jokesFetchFailed(err))),
        takeUntil(action$.pipe(ofType(FETCH_JOKES_CANCELLED)))
      )
    ),
  );
};

export default fetchJokesEpic;

每当FETCH_JOKES 被调度时,这个史诗就会开始ajax 调用,成功调度jokesReceived 操作或失败jokesFetchFailed

我想循环它,所以除非取消,否则端点将在上次调用完成(成功或失败)后再次调用。

我想我可以使用另一个史诗般的 taht 对 JOKES_RECEIVEDFETCH_JOKES_ERROR 动作做出反应,然后调度 FETCH_JOKES 动作应该再次开始 cricle。

import { ofType } from 'redux-observable';
import {
  delay,
  map,
} from 'rxjs/operators';
import {
  JOKES_RECEIVED,
  FETCH_JOKES_CANCELLED,
  FETCH_JOKES_ERROR,
  fetchJokes,
} from '../actions/jokes-action';

const pollJokes = (action$, state$) => {
  return action$.pipe(
    ofType(JOKES_RECEIVED, FETCH_JOKES_ERROR, FETCH_JOKES_CANCELLED),
    delay(2000),
    map(action => {
      console.log('pollJokes.map', action);
      if(action.type === FETCH_JOKES_CANCELLED)
      { 
        console.log("Cancelled")
        return { type: 'POLL_STOPPED' };
      }
      else {
        // loop
        return fetchJokes();
      }
    })
  );
};
export default pollJokes;

但是,当我发送 FETCH_JOKES_CANCELLED 操作时,这不起作用。操作堆栈如下所示:

@INIT
FETCH_JOKES
JOKES_RECEIVED
FETCH_JOKES
JOKES_RECEIVED
...
FETCH_JOKES_CANCELLED
FETCH_JOKES
JOKES_RECEIVED
POLL_STOPPED
FETCH_JOKES
JOKES_RECEIVED
...

我尝试将 takeUntil 添加到 pollJokes 史诗中,但结果同样糟糕

const pollJokes = (action$, state$) => {
  return action$.pipe(
    ofType(JOKES_RECEIVED, FETCH_JOKES_ERROR, FETCH_JOKES_CANCELLED),
    delay(2000),
    map(action => {
      console.log('pollJokes.map', action);
      if(action.type === FETCH_JOKES_CANCELLED)
      { 
        console.log("Cancelled")
        return { type: 'POLL_STOPPED' };
      }
      else {
        // loop
        return fetchJokes();
      }
    }),


    takeUntil(action$.pipe(ofType(FETCH_JOKES_CANCELLED)))


  );
};

使用这种方法,pollJokes 史诗在FETCH_JOKES_CANCELLED 首次发送后立即停止工作。现在我知道史诗在takeUntil 完成。

我该怎么做才能让这种“循环”工作?我猜想实现一个中间件,当JOKES_RECEIVED 调度时,它实际上会调用fetchJokes,但我正在寻找一个全rxjs 解决方案,

【问题讨论】:

    标签: reactjs react-redux polling redux-observable rxjs6


    【解决方案1】:

    你需要使用repeat,为了重新启动你的史诗,一旦它被takeUntil取消了

    const pollJokes = (action$, state$) => {
      return action$.pipe(
        ofType(JOKES_RECEIVED, FETCH_JOKES_ERROR, FETCH_JOKES_CANCELLED),
        delay(2000),
        map(action => {
          console.log('pollJokes.map', action);
          if(action.type === FETCH_JOKES_CANCELLED)
          { 
            console.log("Cancelled")
            return { type: 'POLL_STOPPED' };
          }
          else {
            // loop
            return fetchJokes();
          }
        }),
    
    
        takeUntil(action$.pipe(ofType(FETCH_JOKES_CANCELLED))),
        repeat()
    
      );
    };
    

    【讨论】:

    • 确实有帮助,但是我确定我已经尝试过了:),这个问题还有其他解决方案吗?
    猜你喜欢
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-08
    • 1970-01-01
    • 2019-09-06
    • 2020-12-06
    相关资源
    最近更新 更多