【问题标题】:Update observable from promise based on other observable根据其他 observable 从 promise 更新 observable
【发布时间】:2017-11-14 22:27:17
【问题描述】:

我有一个从我们的后端返回过滤器的服务。该服务有一个方法 getForPage 返回一个 promise,还有一个 getForPage$ 返回一个 observable。

在服务上还有 onEvent 方法,它是一个可观察的,当过滤器发生变化时发出。

现在我希望在 onEvent 发出事件时更新 getForPage$ observable。使用以下代码完成。

getForPage(page: string): Promise<DashboardPageFilter[]> {
    return this.service.call(
        'dashboard.page.filter.getForPage',
        {page}
    );
}

getForPage$(page: string): Observable<DashboardPageFilter[]> {
    let subject = new Subject<DashboardPageFilter[]>();

    this.getForPage(page).then(
        response => subject.next(response),
        response => subject.error(response)
    );

    this.onEvent().subscribe(() => {
        console.log(page);
        this.getForPage(page).then(
            response => subject.next(response),
            response => subject.error(response)
        );
    });

    return subject.asObservable();
}

但是,当我可以路由时,onEvent 上的订阅不会关闭。因此,即使在可观察的主题上不再有活动订阅时,也会调用日志。

如何从可以更新并在路由更改时完成的 promise 中生成 observable?

【问题讨论】:

  • 你提到这是服务的一部分,为什么在服务永远不会被销毁/释放的情况下你需要取消订阅?
  • getForPage$() 每次在onEvent() 上创建一个新订阅。因此,当我在订阅中放置日志并在应用程序中移动一轮,并更改了某些内容时,即使使用旧页面也会多次调用日志。
  • 您可以在this.sub = this.onEvent().subscribe(...)this.sub.unsubscribe()调用getForPage()时保持订阅和取消订阅
  • 这是一种可能性,目前是一个不错的解决方案。但是,不能调用 getForPage$() 两次以显示到不同的列表。
  • 我不明白为什么你需要一个 getForpage():Promise 和一个 getForPage():Observable,而你可以将 promise 转换为 observable 并将 observable 转换为 promise ^^跨度>

标签: angular rxjs


【解决方案1】:

经过更多尝试解决该问题,来自 cmets 的一些想法和重新查看代码后,我找到了问题的解决方案。但是,这还有一个小问题

在代码位于可观察对象之外进行更新之前。使用下面的代码在观察者内部进行更新。

return Observable.create((observer: Observer<DashboardPageFilter[]>) => {
    this.getForPage(page).then(
        response => observer.next(response),
        response => observer.error(response)
    );

    let sub = this.onEvent().subscribe(() => {
        console.log(page);
        this.getForPage(page).then(
            response => observer.next(response),
            response => observer.error(response)
        );
    });

    return function () {
        sub.unsubscribe();
    };
});

主要是回调,取消订阅时取消订阅。

但是在 Angular 中,您需要在调用取消订阅之前将路由更改为其他路由(因此不同的参数不一样)。

【讨论】:

    【解决方案2】:

    您可以改用merge 运算符:

    getForPage$(page: string): Observable<DashboardPageFilter[]> {
    
        const obsFromPromise = Observable.fromPromise(this.getForPage(page));
    
        const result = this.onEvent.switchMap(() => Observable.fromPromise(this.getForPage(page)));
    
        return Observable.merge(obsFromPromise, obsFromEvent)
    }
    

    通过这样做,您的承诺和您的事件将合并为一个无需订阅的 observable。

    有关合并运算符的更多详细信息,请访问rxjs documentation website

    【讨论】:

    • onEvent 通知它不包含过滤器的更改。所以必须收回承诺。所以不幸的是你的解决方案不起作用
    • @MKroeders 哦,我明白了,只需要在 obsFromEvent 上添加一个运算符来将 void 结果映射到 promise ,就是这样:) 稍后再添加。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-27
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    相关资源
    最近更新 更多