加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

从Angular 2服务创建和返回Observable

发布时间:2020-12-17 07:06:14 所属栏目:安全 来源:网络整理
导读:这更像是一个“最佳实践”问题.有三个参与者:组件,服务和模型.组件正在调用服务以从数据库获取数据.该服务正在使用: this.people = http.get('api/people.json').map(res = res.json()); 返回一个Observable. Component可以订阅Observable: peopleService
这更像是一个“最佳实践”问题.有三个参与者:组件,服务和模型.组件正在调用服务以从数据库获取数据.该服务正在使用:

this.people = http.get('api/people.json').map(res => res.json());

返回一个Observable.

Component可以订阅Observable:

peopleService.people
        .subscribe(people => this.people = people);
      }

但是,我真正想要的是Service返回一个Model对象数组,该对象是从Service从数据库中检索的数据创建的.我意识到Component可以在subscribe方法中创建这个数组,但我认为如果服务这样做并使其可供Component使用它会更干净.

服务如何创建一个包含该数组的新Observable并返回该数组?

解决方法

更新:9/24/16 Angular 2.0稳定

这个问题仍然有很多流量,所以,我想更新它.随着来自Alpha,Beta和7个RC候选人的变化的疯狂,我停止更新我的SO答案,直到他们稳定.

这是使用Subjects和ReplaySubjects的完美案例

我个人更喜欢使用ReplaySubject(1),因为它允许最新存储的值在新订阅者附加时传递,即使是在迟到时:

let project = new ReplaySubject(1);

//subscribe
project.subscribe(result => console.log('Subscription Streaming:',result));

http.get('path/to/whatever/projects/1234').subscribe(result => {
    //push onto subject
    project.next(result));

    //add delayed subscription AFTER loaded
    setTimeout(()=> project.subscribe(result => console.log('Delayed Stream:',result)),3000);
});

//Output
//Subscription Streaming: 1234
//*After load and delay*
//Delayed Stream: 1234

因此,即使我迟到或需要加载以后我也可以随时获得最新的电话,而不用担心错过回调.

这也允许您使用相同的流向下推送到:

project.next(5678);
//output
//Subscription Streaming: 5678

但是,如果你100%确定,你只需要做一次电话怎么办?留下开放的主题和可观察的东西并不好,但总会有“怎么办?”

这就是AsyncSubject进来的地方.

let project = new AsyncSubject();

//subscribe
project.subscribe(result => console.log('Subscription Streaming:',result),err => console.log(err),() => console.log('Completed'));

http.get('path/to/whatever/projects/1234').subscribe(result => {
    //push onto subject and complete
    project.next(result));
    project.complete();

    //add a subscription even though completed
    setTimeout(() => project.subscribe(project => console.log('Delayed Sub:',project)),2000);
});

//Output
//Subscription Streaming: 1234
//Completed
//*After delay and completed*
//Delayed Sub: 1234

真棒!即使我们关闭了主题,它仍然会回复它加载的最后一件事.

另一件事是我们如何订阅该http调用并处理响应. Map非常适合处理响应.

public call = http.get(whatever).map(res => res.json())

但是,如果我们需要嵌套这些电话呢?是的,您可以使用具有特殊功能的主题:

getThing() {
    resultSubject = new ReplaySubject(1);

    http.get('path').subscribe(result1 => {
        http.get('other/path/' + result1).get.subscribe(response2 => {
            http.get('another/' + response2).subscribe(res3 => resultSubject.next(res3))
        })
    })
    return resultSubject;
}
var myThing = getThing();

但这很多,意味着你需要一个功能来完成它.输入FlatMap:

var myThing = http.get('path').flatMap(result1 => 
                    http.get('other/' + result1).flatMap(response2 => 
                        http.get('another/' + response2)));

很好,var是一个可观察的,从最终的http调用中获取数据.

好的很棒,但我想要一个angular2服务!

我接到你了:

import { Injectable } from '@angular/core';
import { Http,Response } from '@angular/http';
import { ReplaySubject } from 'rxjs';

@Injectable()
export class ProjectService {

  public activeProject:ReplaySubject<any> = new ReplaySubject(1);

  constructor(private http: Http) {}

  //load the project
  public load(projectId) {
    console.log('Loading Project:' + projectId,Date.now());
    this.http.get('/projects/' + projectId).subscribe(res => this.activeProject.next(res));
    return this.activeProject;
  }

 }

 //component

@Component({
    selector: 'nav',template: `<div>{{project?.name}}<a (click)="load('1234')">Load 1234</a></div>`
})
 export class navComponent implements OnInit {
    public project:any;

    constructor(private projectService:ProjectService) {}

    ngOnInit() {
        this.projectService.activeProject.subscribe(active => this.project = active);
    }

    public load(projectId:string) {
        this.projectService.load(projectId);
    }

 }

我是观察者和观察者的忠实粉丝,所以我希望这次更新有所帮助!

原始答案

我认为这是使用Observable Subject或在Angular2中使用EventEmitter的用例.

在您的服务中,您可以创建一个EventEmitter,允许您将值推送到它上面.在Alpha 45中你必须用toRx()转换它,但我知道他们正在努力摆脱它,所以在Alpha 46中你可以简单地返回EvenEmitter.

class EventService {
  _emitter: EventEmitter = new EventEmitter();
  rxEmitter: any;
  constructor() {
    this.rxEmitter = this._emitter.toRx();
  }
  doSomething(data){
    this.rxEmitter.next(data);
  }
}

这种方式具有单个EventEmitter,您可以使用不同的服务功能.

如果您想直接从通话中返回一个observable,您可以执行以下操作:

myHttpCall(path) {
    return Observable.create(observer => {
        http.get(path).map(res => res.json()).subscribe((result) => {
            //do something with result. 
            var newResultArray = mySpecialArrayFunction(result);
            observer.next(newResultArray);
            //call complete if you want to close this stream (like a promise)
            observer.complete();
        });
    });
}

这将允许您在组件中执行此操作:
peopleService.myHttpCall(‘path’).subscribe(people => this.people = people);

并搞乱你服务中的电话结果.

我喜欢自己创建EventEmitter流,以防我需要从其他组件访问它,但我可以看到两种方式都工作…

这是一个使用事件发射器显示基本服务的plunker:Plunkr

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读