Reactjs 如何在react redux epic中取消http请求

Reactjs 如何在react redux epic中取消http请求,reactjs,react-redux,rxjs,axios,observable,Reactjs,React Redux,Rxjs,Axios,Observable,我想取消在redux epic中调用的http请求。我的http请求使用axios,它可以提供取消令牌。。。 但是如果我创建了取消令牌,我在哪里使用它呢 我使用rxjs/from将我的http请求转换为可观察的,并使用rxjs中的takeUntil来取消http请求的订阅。。。但这真的“取消”了我的http请求吗?如何确保http请求实际被取消?我不需要使用取消令牌吗 const loadApplicationNotesEpic: Epic<Action, Action, RootStat

我想取消在redux epic中调用的http请求。我的http请求使用axios,它可以提供取消令牌。。。 但是如果我创建了取消令牌,我在哪里使用它呢

我使用rxjs/from将我的http请求转换为可观察的,并使用rxjs中的takeUntil来取消http请求的订阅。。。但这真的“取消”了我的http请求吗?如何确保http请求实际被取消?我不需要使用取消令牌吗

const loadApplicationNotesEpic: Epic<Action, Action, RootState> = action$ =>
  action$.pipe(
    filter(isActionOf(actions.getApplicationNotes)),
    map(action => action.payload),
    switchMap(applicationId => {
       // create cancel token here?: 
       // const cancelToken = axios.CancelToken;
       // where to use cancelToken?
      return from(axios.get(apiUrl(`/${applicationId}/notes`))).pipe(
        takeUntil(filterAction(action$, actions.getApplicationNotesCancel)),
        map(notes => actions.getApplicationNotesSuccess(notes, applicationId)),
        catchError(error => {
          console.error(error);
          return of(actions.getApplicationNotesError(error));
        }),
      );
    }),
  );
const-loadApplicationNotesEpic:Epic=action$=>
动作$.pipe(
过滤器(isActionOf(actions.getApplicationNotes)),
映射(action=>action.payload),
开关映射(应用程序ID=>{
//是否在此处创建取消令牌?:
//const cancelToken=axios.cancelToken;
//在哪里使用取消令牌?
从(axios.get(apirl(`/${applicationId}/notes`)).pipe返回(
takeUntil(filterAction(action$,actions.getApplicationNotesCancel)),
映射(notes=>actions.getApplicationNotesAccess(notes,applicationId)),
catchError(错误=>{
控制台错误(error);
返回(actions.getApplicationNotesError(错误));
}),
);
}),
);

以下是一个我认为您可能正在寻找的示例。我不熟悉axios。我刚刚从他们的网站上摘取了取消的例子

我还将
switchMap
替换为
mergeMap
,因为我认为如果

..
    filter(isActionOf(actions.getApplicationNotes)),
    map(action => action.payload),
..
然后,它将取消对switchMap返回的上一个observable的订阅,而不必取消对
axios.get的调用

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

const loadApplicationNotesEpic: Epic<Action, Action, RootState> = action$ =>
  action$.pipe(
    filter(isActionOf(actions.getApplicationNotes)),
    map(action => action.payload),
    mergeMap(applicationId => {
      // create cancel token here?:
      // const cancelToken = axios.CancelToken;
      // where to use cancelToken?

      const promise$ = from(
        axios.get(
          apiUrl(`/${applicationId}/notes`, { cancelToken: source.token })
        )
      ).pipe(
        catchError(error => {
          console.error(error);
          return of(actions.getApplicationNotesError(error));
        })
      );

      const cancelled$ = filterAction(
        action$,
        actions.getApplicationNotesCancel
      ).pipe(mapTo("cancelled"));

      return race(promise$, cancelled$).pipe(
        mergeMap(winner => {
          if (winner === "cancelled") {
            return of(EMPTY).pipe(
                     tap(() => source.cancel('Operation canceled by the user.')),
                     ignoreElements())
          }

          return of(winner).pipe(
            map(notes =>
              actions.getApplicationNotesSuccess(notes, applicationId)
            )
          );
        })
      );
    })
  );
const CancelToken=axios.CancelToken;
const source=CancelToken.source();
const loadApplicationNotesEpic:Epic=action$=>
动作$.pipe(
过滤器(isActionOf(actions.getApplicationNotes)),
映射(action=>action.payload),
合并映射(应用程序ID=>{
//是否在此处创建取消令牌?:
//const cancelToken=axios.cancelToken;
//在哪里使用取消令牌?
const promise$=来自(
axios.get(
APIRL(`/${applicationId}/notes`,{cancelToken:source.token})
)
).烟斗(
catchError(错误=>{
控制台错误(error);
返回(actions.getApplicationNotesError(错误));
})
);
常量已取消$=filterAction(
行动$,
actions.getApplicationNotesCancel
).管道(映射到(“已取消”);
返回比赛(承诺$,取消$)。管道(
合并地图(获胜者=>{
如果(获胜者==“取消”){
返回(空)管道(
轻触(()=>source.cancel('用户已取消操作'),
ignoreElements())
}
返回(赢家)。管道(
地图(注=>
actions.getApplicationNotesAccess(notes,applicationId)
)
);
})
);
})
);

以下是一个我认为您可能正在寻找的示例。我不熟悉axios。我刚刚从他们的网站上摘取了取消的例子

我还将
switchMap
替换为
mergeMap
,因为我认为如果

..
    filter(isActionOf(actions.getApplicationNotes)),
    map(action => action.payload),
..
然后,它将取消对switchMap返回的上一个observable的订阅,而不必取消对
axios.get的调用

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

const loadApplicationNotesEpic: Epic<Action, Action, RootState> = action$ =>
  action$.pipe(
    filter(isActionOf(actions.getApplicationNotes)),
    map(action => action.payload),
    mergeMap(applicationId => {
      // create cancel token here?:
      // const cancelToken = axios.CancelToken;
      // where to use cancelToken?

      const promise$ = from(
        axios.get(
          apiUrl(`/${applicationId}/notes`, { cancelToken: source.token })
        )
      ).pipe(
        catchError(error => {
          console.error(error);
          return of(actions.getApplicationNotesError(error));
        })
      );

      const cancelled$ = filterAction(
        action$,
        actions.getApplicationNotesCancel
      ).pipe(mapTo("cancelled"));

      return race(promise$, cancelled$).pipe(
        mergeMap(winner => {
          if (winner === "cancelled") {
            return of(EMPTY).pipe(
                     tap(() => source.cancel('Operation canceled by the user.')),
                     ignoreElements())
          }

          return of(winner).pipe(
            map(notes =>
              actions.getApplicationNotesSuccess(notes, applicationId)
            )
          );
        })
      );
    })
  );
const CancelToken=axios.CancelToken;
const source=CancelToken.source();
const loadApplicationNotesEpic:Epic=action$=>
动作$.pipe(
过滤器(isActionOf(actions.getApplicationNotes)),
映射(action=>action.payload),
合并映射(应用程序ID=>{
//是否在此处创建取消令牌?:
//const cancelToken=axios.cancelToken;
//在哪里使用取消令牌?
const promise$=来自(
axios.get(
APIRL(`/${applicationId}/notes`,{cancelToken:source.token})
)
).烟斗(
catchError(错误=>{
控制台错误(error);
返回(actions.getApplicationNotesError(错误));
})
);
常量已取消$=filterAction(
行动$,
actions.getApplicationNotesCancel
).管道(映射到(“已取消”);
返回比赛(承诺$,取消$)。管道(
合并地图(获胜者=>{
如果(获胜者==“取消”){
返回(空)管道(
轻触(()=>source.cancel('用户已取消操作'),
ignoreElements())
}
返回(赢家)。管道(
地图(注=>
actions.getApplicationNotesAccess(notes,applicationId)
)
);
})
);
})
);

你想在(..)的
过滤器操作(action$,actions.getApplicationNotesCancel)
之间竞争,而不是在()的
之间竞争吗?我知道我特别想使用
takeUntil
专门用于
from(axios函数)
observed为什么要专门使用takeUntil?from返回的可观察对象只发出1个事件。我认为您正在寻找的是在承诺履行或取消操作之间的竞争。这将允许您检查2人中的哪一人赢得比赛,如果取消比赛,您将调用相应的函数通知axios?@chautelly-hmm。。。好吧,这是有道理的,我一定会尝试一下!我对rxjs有点陌生,没有意识到race是一个选项。你想在(…)
filterAction(action$,actions.getApplicationNotesCancel)
之间进行比赛,而不是在().takeUntil()的
之间进行比赛吗?@Chautely..嗯,我不太清楚你所说的比赛是什么意思?我知道我特别想使用
takeUntil
专门用于
from(axios函数)
observed为什么要专门使用takeUntil?由from返回的可观测值仅发出1个eve