【问题标题】:How to have an effect wait on an Observable with @ngrx/effects如何使用 @ngrx/effects 对 Observable 产生效果等待
【发布时间】:2017-04-20 08:25:39
【问题描述】:

我在 Angular 2 应用程序中使用 @ngrx/effects,但在尝试实现依赖于基于应用程序状态的条件的效果时遇到了一些问题。

在我的状态下,我有一张 Location -> Capabilities 地图,以locationId 为键(以及其他 Location -> * 地图)。当ACTION_A 发生时,我只希望它在当前位置具有最新功能时继续。当ACTION_A 被调度时,功能可能已经是最新的,但是,应用程序也可能正在加载新功能。

使用下面的代码,一旦ACTION_A 被调度一次,isOutOfDate 就会在每次 any 动作被调度到商店时被调用。因此,即使在满足最新过滤器之后,observable 似乎仍然处于活动状态。但是,如果 getCapabilitiesgetCapabilitiesWorking 替换,那么 isOutOfDate 只会在每次调度 ACTION_A 操作时满足过滤条件时才被调用,正如我对任一实现所期望的那样。

所以,我似乎错过了 combineLatestfiltertake 的工作原理......

或者也许我正在接近这一切都错了......

我希望能够为我的“当前位置”选择器使用通用功能

有什么想法吗?

@Effect() route$ = actions$
    .ofType(ACTION_A)
    .switchMap(() => this._store.let(getCapabilities)
        .filter(capabilities => !isOutOfDate(capabilities))
        .take(1)
    )
    .map( do some stuff );

// Selector function that causes excess observable emits
export const getCapabilities =
     compose(fromLocations.currentLocationLookup(fromLocations.getCapabilities), fromRoot.getLocations);

// Selector function works as expected
export const getCapabilitiesWorking = function (state$: Observable<AppState>): Observable<Capability> {
    return state$
        .let(fromRoot.getLocations)
        .map(l => l.capabilitiesByLocation[l.currentId]);
};

// fromLocations
// -------------

export function getCapabilities(state$: Observable<LocationsState>): Observable<{ [id: string]: Capability }> {
    return state$.map(s => s.capabilitiesByLocation);
}

// Find the value in 'collection' corresponding to the current location
export function currentLocationLookup<T>(
    collection: (state$: Observable<LocationsState>) => Observable<{ [id: string]: T }>
): (state$: Observable<LocationsState>) => Observable<T> {
    return (state$: Observable<LocationsState>): Observable<T> => {
        return Observable.combineLatest(
            state$.let(getCurrentLocation),
            state$.let(collection),
            (locId, map) => map[locId]
        );
    };
}

编辑:澄清一下,isOutOfDate 函数不断被调用,但是“做一些事情”并没有......

【问题讨论】:

    标签: typescript rxjs ngrx


    【解决方案1】:

    您可以尝试将 switchMap 中的过滤器替换为skipWhile

    所以效果是:

    @Effect() route$ = actions$
    .ofType(ACTION_A)
    .switchMap(() => this._store.let(getCapabilities)
        .skipWhile(capabilities => !isOutOfDate(capabilities))
        .take(1)
    )
    .map( do some stuff );
    

    这在类似的用例中帮助了我:)

    【讨论】:

    • 如果等待另一个 Observable,请使用 skipUntilskipWhile 根据源 observable 测试条件。
    【解决方案2】:

    withLatestFrom 不起作用,因为结果 observable 只有在源发出(动作调度)时才会发出输出,根据你需要combineLatest 的文档,所以:

    @Effect() route$ = actions$
      .ofType(ACTION_A)
      .combineLatest(this._store.let(getCapabilities))
      .filter(([action, capabilities]) =>!isOutOfDate(capabilities)) 
      .map( do some stuff );
    

    【讨论】:

    • 这不是最佳实践,至少在今天是这样。
    【解决方案3】:

    尝试使用withLatestFrom 方法。你的效果可能看起来像

    @Effect() route$ = actions$
    .ofType(ACTION_A)
    .withLatestFrom(this._store.let(getCapabilities))
    .filter(([action, capabilities]) =>!isOutOfDate(capabilities)) 
    .map( do some stuff );
    

    【讨论】:

    • 我考虑过这种可能性,但是,这并不是我所需要的。它将采用商店中可能尚未填充的任何当前值。然后过滤器被应用在错误的位置。我需要它“等待”直到填充功能,然后产生“做一些事情”的效果
    猜你喜欢
    • 2017-11-19
    • 2018-06-16
    • 1970-01-01
    • 2020-10-31
    • 2022-07-11
    • 1970-01-01
    • 2019-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多