这更像是一个"best practices"问题 . 有三个玩家: Component
, Service
和 Model
. Component
正在调用 Service
以从数据库中获取数据 . Service
正在使用:
this.people = http.get('api/people.json').map(res => res.json());
返回 Observable
.
Component
可以订阅 Observable
:
peopleService.people
.subscribe(people => this.people = people);
}
但是,我真正想要的是 Service
返回 Array of Model
对象,这些对象是从 Service
从数据库中检索的数据创建的 . 我意识到 Component
可以在subscribe方法中创建这个数组,但我认为如果服务这样做并使其可用于 Component
则会更清晰 .
Service
如何创建一个包含该数组的新 Observable
并返回该数组?
6 回答
UPDATE: 9/24/16 Angular 2.0 Stable
这个问题仍然有很多流量,所以,我想更新它 . 随着来自Alpha,Beta和7个RC候选人的变化的疯狂,我停止更新我的SO答案,直到他们稳定 .
这是使用Subjects和ReplaySubjects的完美案例
我个人更喜欢使用
ReplaySubject(1)
,因为它允许在新订阅者附加时传递最后一个存储的值,即使是在迟到时:因此,即使我迟到或需要加载以后我也可以随时获得最新的电话,而不用担心错过回调 .
这也允许您使用相同的流向下推送到:
但是,如果你100%确定,你只需要做一次电话怎么办?留下开放的主题和可观察的东西并不总是 "What If?"
这就是AsyncSubject的用武之地 .
真棒!即使我们关闭了主题,它仍然会回复它加载的最后一件事 .
另一件事是我们如何订阅该http调用并处理响应 . Map非常适合处理响应 .
但是,如果我们需要嵌套这些电话呢?是的,您可以使用具有特殊功能的主题:
但这很多,意味着你需要一个功能来完成它 . 输入FlatMap:
很好,
var
是一个可以从最终的http调用中获取数据的observable .OK thats great but I want an angular2 service!
我接到你了:
我是观察者和观察者的忠实粉丝,所以我希望这次更新有所帮助!
Original Answer
我认为这是使用Observable Subject或
Angular2
EventEmitter
的用例 .在您的服务中,您创建一个
EventEmitter
,允许您将值推送到它上面 . 在 Alpha 45 中你必须用toRx()
转换它,但我知道他们正在努力摆脱它,所以在 Alpha 46 中你可以简单地返回EvenEmitter
.这种方式具有单个
EventEmitter
,您现在可以使用不同的服务功能 .如果您想直接从通话中返回一个observable,您可以执行以下操作:
这将允许您在组件中执行此操作:
peopleService.myHttpCall('path').subscribe(people => this.people = people);
并搞乱你服务中的电话结果 .
我喜欢自己创建
EventEmitter
流,以防我需要从其他组件访问它,但我可以看到两种方式都工作...这是一个使用事件 Launcher 显示基本服务的plunker:Plunkr
这是Angular2 docs中有关如何创建和使用自己的Observable的示例:
The Service
The Component
完整且有效的例子可以在这里找到:https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service
我想补充说,如果创建的对象是静态的,而不是来自http,可以这样做:
从回答我关于观察者和静态数据的问题:https://stackoverflow.com/a/35219772/986160
我参加派对有点晚了,但我认为我的方法的优势在于它没有使用EventEmitters和Subjects .
所以,这里's my approach. We can' t远离subscribe(),我们不想这样做 . 在这种情况下,我们的服务将返回
Observable<T>
与一个拥有我们珍贵货物的观察员 . 从调用者,我们将初始化一个变量Observable<T>
,它将获得服务的Observable<T>
. 接下来,我们将订阅此对象 . 最后,你得到你的"T"!来自您的服务 .首先,我们的人员服务,但你的服务不传递参数,这更现实:
好的,正如您所看到的,我们正在返回
Observable
类型为"people" . 方法的签名,甚至是这样说的!我们将_people
对象塞入我们的观察者 . 接下来我们将从Component中的调用者访问此类型!在组件中:
我们初始化
_peopleObservable
从PeopleService
返回Observable<people>
. 然后,我们订阅了这个属性 . 最后,我们将this.people
设置为我们的数据(people
)响应 .以这种方式构建服务与典型服务相比具有一个主要优势:map(...)和component:“subscribe(...)”模式 . 在现实世界中,我们需要将json映射到我们类中的属性,有时候,我们会在那里做一些自定义的东西 . 所以这种映射可以在我们的服务中进行 . 而且,通常,因为我们的服务调用不会被使用一次,但是,可能在我们的代码中的其他地方,我们不必再次在某个组件中执行该映射 . 而且,如果我们为人们增加一个新领域怎么办?....
请注意,您正在使用Observable#map将基本Observable发出的原始
Response
对象转换为JSON响应的已解析表示 .如果我理解正确,你想再次
map
. 但这一次,将原始JSON转换为Model
的实例 . 所以你会做类似的事情:所以,你开始使用一个Observable发出
Response
对象,将其转换为一个observable,它发出该响应的解析JSON的对象,然后将其转换为另一个observable,将原始JSON转换为模型数组 .在service.ts文件中 -
一个 . 从observable / of导入'of'
湾创建一个json列表
C . 使用Observable.of()返回json对象
防爆 . -
在我们调用服务的get函数的组件中 -