ОНОВЛЕННЯ: 9/24/16 Кутовий 2.0 Стабільний
Це питання все ще отримує багато трафіку, тому я хотів його оновити. З божевіллям змін від Альфа, Бета та 7 кандидатів у РК я перестав оновлювати свої відповіді, поки вони не стали стабільними.
Це ідеальний випадок для використання предметів та 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-дзвінок та обробляли відповідь. Карта чудова для обробки відповіді.
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
що дозволяє наштовхувати на нього значення. В Альфа 45 вам потрібно це перетворити toRx()
, але я знаю, що вони працювали над тим, щоб позбутися цього, тому в Альфа 46 ви зможете просто повернути це EvenEmitter
.
class EventService {
_emitter: EventEmitter = new EventEmitter();
rxEmitter: any;
constructor() {
this.rxEmitter = this._emitter.toRx();
}
doSomething(data){
this.rxEmitter.next(data);
}
}
Цей спосіб має єдиний EventEmitter
варіант, на який зараз можуть розповсюджуватися різні ваші сервісні функції.
Якщо ви хочете повернути спостережуваний безпосередньо з дзвінка, ви можете зробити щось подібне:
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
потік самостійно, якщо мені потрібно отримати доступ до нього з інших компонентів, але я можу побачити, як працюють два способи ...
Ось планкер, який показує основну послугу з емітером подій: Plunkr