【问题标题】:Angular 2: loading bar component with Observable streamsAngular 2:使用 Observable 流加载 bar 组件
【发布时间】:2017-02-16 14:37:10
【问题描述】:

我正在寻找一种在observable stream 上使用loading bar component 的方法?

我有一个component,它使用async pipe 显示来自observable 的数据。这个 Observable 还可以操作数据,例如使用 map。

目前我在组件中有这个:

 this.listData$ = this.http.get('/itemList')
            .map(data => this.manipulate(data))

在模板中:

{{listData$ | async}}

服务器可以将数据返回为empty []'unavailable'array 的项目。

如何接入流并提供加载组件,该组件在加载数据时会显示加载栏,并在为空或不可用时显示错误消息?类似的东西......

this.listData$ = this.http.get('/itemList')
                //.something here??
                .map(data => this.manipulate(data))


<loading-bar [data]='listData$' [noDataMsg]='"no data"' [errorMsg]='unavailable'>
    {{listData$ | async}}
</loading-bar>

理想情况下,我想继续使用async pipe,而不是订阅我的组件。但是,将 Observable 传递给 loading-bar 组件并在那里订阅,这使得2 http calls...然后我需要在 Observable 上使用 .share()...

你们用什么方法来显示加载、没有数据和错误消息的流?

【问题讨论】:

  • 实际上你可以使用一些loading标志并在http之前设置为true,如果你想避免订阅,在map内部设置为false。所以你的加载可以监听loading变量状态
  • 你可以使用do操作符,它允许你在不使用map的情况下添加操作,比如this.http.get(...).do(loading = false).map(... =&gt; ...);

标签: angular


【解决方案1】:

您将 observable 传递给 &lt;loading-bar&gt; 的想法似乎很好。

如果您唯一关心的是避免多次订阅,您有两种选择:

1.分享原始 observable

this.listData$ = this.http.get('/itemList')
                   .map(data => this.manipulate(data))
                   .share();

2。创建中介BehaviorSubject

主题将充当原始可观察对象和模板之间的“缓冲区”:

  • 您将原始 obs 的值通过管道传输到您的 BehaviorSubject 中。
  • 您的模板订阅(通过 async)您的 BehaviorSubject。

模板中仍然可以有多个订阅,但它们是针对您的主题的。然而,原始的 observable 仅由您的主题订阅一次(这意味着 HTTP 请求仅执行一次)。

代码会是这样的(我还没有测试过):

在课堂上:

this.listDataBuffer$ = new BehaviorSubject<any>(null);
this.listData$.subscribe(listDataBuffer$);

在模板中:

{{listDataBuffer$ | async}}

附加说明:

  1. 您说您的原始 observable 发出一个项目数组。这意味着这是一个二元操作:要么你拥有所有的项目,要么你没有。使用此配置,您将永远无法显示进度。您只能在“加载”和“完成”两种状态之间切换。

  2. 当您传递字符串文字时,无需在输入周围使用[ ]

// YOUR CODE:
<loading-bar [noDataMsg]='"no data"' [errorMsg]='"unavailable"'>

// COULD BE:
<loading-bar noDataMsg="no data" errorMsg="unavailable">

【讨论】:

  • 谢谢!这似乎是一个合理的建议,我将在今天晚些时候尝试这些概念并报告回来。
  • 仔细看:this.listDataBuffer$ = new BehaviorSubject(null); this.listData$.subscribe(listDataBuffer$);现在不是意味着我需要取消订阅 onDestroy 中的 listData$ 吗?我认为使用 .share() 比创建主题并不必担心退订更痛苦,还是我错过了什么?再次感谢
  • 你完全正确。根据stackoverflow.com/a/40819423/1153681。回想起来,我的解决方案似乎有点矫枉过正,我会相应地更新我的答案。
  • 谢谢,不知道你是否知道,但目前我不清楚幕后的 .share() 是否执行 .publishLast()。意思是,如果加载订阅太晚并错过数据的“轻微”机会,但到目前为止,由于 Angular 的初始化周期,组件和加载组件似乎同时订阅。更糟糕的是,我总是可以用 .publishLast().refCount() 替换 .share()。
  • 好。我不是 share() 专家。我确实在这里和那里看到它相当于 .publishLast().refCount() 但我不知道它是否真的在后台使用了这些运算符。
猜你喜欢
  • 1970-01-01
  • 2016-07-17
  • 1970-01-01
  • 1970-01-01
  • 2016-11-20
  • 2018-02-15
  • 2017-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多