如果当前订阅尚未完成,则取消新订阅

时间:2018-09-01 14:18:12

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

我有一个史诗般的动作,它以React组件的componentDidMount方法调度从本地服务器获取公司。 利用返回的数据,我实例化了模型并将其传递给执行其工作的reducer。

史诗般的动作如下所示:

export const fetchCompaniesEpic = (action$: Observable<Action>): Observable<Action> =>
    action$.pipe(
        ofType(FETCH_COMPANIES),
        delay(5000),
        switchMap((action: any) =>
            ajax(COMPANIES_RESOURCE_URL).pipe(
                map((data: any) =>
                    data.response.map((value: any) => new Company(value.symbol, value.name, value.lastSale, value.marketCap, value.sector, value.industry))
                ),
                map((companies: Company[]) => fetchCompaniesFulfilled(companies))
            )
        )
    );

对于redux-observable来说还很陌生,我想向大家提出3个问题:

1)取消所有同时进行的新订阅(以及http请求)的最佳方法是什么? (进行中也意味着在延迟5秒内)

2)实现我所有目标的最佳方法是什么?我是在做任何不良做法还是做得更好? (rxjs,react,redux)

3)在我分派此操作的地方订阅的最佳方法是什么?像dispatch({type: FETCH_COMPANIES}).subscribe

p.s。这只是一个理论上的例子,因为我想很好地理解它是如何工作的,所以不要专注于延迟等的真正用途。

2 个答案:

答案 0 :(得分:1)

为了更详细地说明@Xinan写的内容,您可以考虑以下旨在模拟您的情况的示例

const action$ = new Subject<number>();

const ajax = (delay: number) => {
    const ajax$ = new Subject<any>();
    setTimeout(() => {
        ajax$.next('delay ' + delay);
        ajax$.complete();
    }, delay);
    return ajax$.asObservable();
};

action$
.pipe(
    switchMap(delay => ajax(delay)),  // delay 1001, delay 1002
    // exhaustMap(delay => ajax(delay)),  // delay 3000, delay 1002
)
.subscribe(console.log);

setTimeout(() => {action$.next(3000);}, 0);  // action$ emission 1
setTimeout(() => {action$.next(1000);}, 1000);  // action$ emission 2 
setTimeout(() => {action$.next(1001);}, 1500); // action$ emission 3
setTimeout(() => {action$.next(1002);}, 3502); // action$ emission 4

action$的Observable分别在0、1000、1500和3502毫秒后发出4次。

每次发出action$时,我们都会创建一个ajax可观察对象,它在指定为action$的延迟之后本身只会发出一次,然后完成。

因此,例如,由ajax的第一个通知创建的action$ Observable(即 action $发射1 )将在3秒后发射并完成,而第二个ajax会在2秒后发射(由于 action $发射2的延迟,所以1秒 +由于ajax的发射而延迟1秒)。< / p>

在此模拟中,如果您使用switchMap,则会在控制台上看到

delay 1001
delay 1002

原因是 action $排放3 会发射,而 action $排放1 action $排放2 仍在飞行,因此它们是根据switchMap的逻辑完成的,并由 action $排放3 取消订阅。发出 action $排放4 后,没有其他 action $排放,因此它可以正常完成,以便在控制台上打印diplay 1002

相反,如果将switchMap替换为exaustMap,您将得到

delay 3000
delay 1002

原因是先前推理的镜像。 action $排放2 action $排放3 被杀死,因为 action $排放1 仍在飞行中。

答案 1 :(得分:0)

我猜您需要的是exaustMap,基本上它的作用与switchMap相反

switchMap取消上一个,而改用新的

exaustMap取消新的并保留现有的(如果尚未完成的话)