2017-08-04 61 views
2

我正在尝试创建一个简单的可重构可观察史诗,它可以反弹并且可以取消。我的代码:反弹和取消可重复观察

export const apiValidate = action$ => { 
    return action$.ofType(validateRequestAction) 
     .debounceTime(250) 
     .switchMap((action) => (
      Observable.ajax({ 
       url: url, 
       method: 'GET', 
       crossDomain: true, 
       headers: { 
        "Content-Type": 'application/json' 
       }, 
       responseType: 'json' 
      }) 
      .map(payload => (new APISuccessValidate())) 
      .takeUntil(action$.ofType(validateCancelAction)) 
      .catch(payload => ([new APIFailureValidate()])) 
    )); 
}; 

代码只有时才有效。根据服务器的响应速度,我认为可能会出现两种情况之一。

情景1(作品):

Time 0ms - Fire validateRequestAction 
Time 250ms - Ajax request occurs 
Time 251ms - Fire validateCancelAction 
Time 501ms - validateCancelAction passes debounce and cancels properly 
Nothing else occurs 

方案2(断)

Time 0ms - Fire validateRequestAction 
Time 250ms - Ajax request occurs 
Time 251ms - Fire validateCancelAction 
Time 400ms - Ajax returns, APISuccessValidate action fired 
Time 501ms - validateCancelAction passes debounce and there is nothing to cancel 

有没有一种方法,我可以写我的史诗,使得只有validateCancelAction可以绕过debounceTime并取消阿贾克斯呼吁没有等待?

谢谢!

回答

3

你实际上只是在清除你的匹配validateRequestAction,但你的.takeUntil(action$.ofType(validateCancelAction))没有任何反弹。我可能是错的,但是如果可以在之前发送取消动作该动作已经超过了去抖动,那么取消该动作将会取消而不是,因为ajax请求没有取消开始了,也没有takeUntil。通过不允许取消直到你的副作用(本例中的ajax)已经开始并且takeUntil正在倾听可能的取消。

在您的用户界面中,您不会让用户能够取消,直到设置了某种状态为止。由于我们的史诗需要告诉redux何时翻转,我们需要发出一个动作,我们将在减速器中侦听。

最简单的方法是使用startWith操作:

export const apiValidate = action$ => { 
    return action$.ofType(validateRequestAction) 
     .debounceTime(250) 
     .switchMap((action) => (
      Observable.ajax({ 
       url: url, 
       method: 'GET', 
       crossDomain: true, 
       headers: { 
        "Content-Type": 'application/json' 
       }, 
       responseType: 'json' 
      }) 
      .map(payload => (new APISuccessValidate())) 
      .takeUntil(action$.ofType(validateCancelAction)) 
      .catch(payload => ([new APIFailureValidate()])) 
      .startWith({ type: 'validateRequestActionStarted' }) // <-- here 
    )); 
}; 

因此,在这个例子中,一些减速会听validateRequestActionStarted,并改变一些国家的UI便会知道,我们应该给他们取消的能力。


阻止那场比赛将是takeUntil的顶级流完全和一个完全不同的方式则刚刚“重启”使用repeat,如果它被取消的史诗。所以这会在我们取消时关闭所有的东西。任何悬而未决的ajaxs和任何未决的debounces。

export const apiValidate = action$ => { 
    return action$.ofType(validateRequestAction) 
     .debounceTime(250) 
     .switchMap((action) => (
      Observable.ajax({ 
       url: url, 
       method: 'GET', 
       crossDomain: true, 
       headers: { 
        "Content-Type": 'application/json' 
       }, 
       responseType: 'json' 
      }) 
      .map(payload => (new APISuccessValidate())) 
      .catch(payload => ([new APIFailureValidate()])) 
     )) 
     .takeUntil(action$.ofType(validateCancelAction)) 
     .repeat(); 
}; 

值得一提的是,我使用的术语史诗,并重新启动,以帮助我们的概念化特定领域,但这大多只是正常RxJS所以它的终极版,可观察到的普遍适用的外面。一个“史诗”只是我们的一个函数模式的一个词,它接受一系列操作(输入)并返回一系列操作(输出)。

+0

感谢您花时间解释我对抖动动作的误解,这对我帮助了很多,正确理解了这个问题。我尝试了你提供的第二个解决方案,它完美的工作!我也不知道startWith,我相信这将在未来派上用场。 非常感谢! –

+0

不客气!我强烈建议花一些时间真正理解_why_它的作品:)祝你好运! – jayphelps

+0

是的,我现在正在通过所有文档工作=) –