อัปเดต: 9/24/16 Angular 2.0 Stable
คำถามนี้ยังคงได้รับการเข้าชมจำนวนมากดังนั้นฉันจึงต้องการอัปเดต ด้วยความบ้าคลั่งของการเปลี่ยนแปลงจากผู้สมัคร Alpha, Beta และ 7 RC ฉันจึงหยุดอัปเดตคำตอบ SO ของฉันจนกว่าจะมีเสถียรภาพ
นี่เป็นกรณีที่สมบูรณ์แบบสำหรับการใช้SubjectsและReplaySubjects
ฉันชอบใช้เป็นการส่วนตัวReplaySubject(1)
เนื่องจากอนุญาตให้ส่งค่าที่เก็บไว้ล่าสุดเมื่อสมาชิกใหม่แนบแม้ว่าจะสาย
let project = new ReplaySubject(1);
project.subscribe(result => console.log('Subscription Streaming:', result));
http.get('path/to/whatever/projects/1234').subscribe(result => {
project.next(result));
setTimeout(()=> project.subscribe(result => console.log('Delayed Stream:', result)), 3000);
});
ดังนั้นแม้ว่าฉันจะแนบสายหรือต้องโหลดในภายหลังฉันก็สามารถรับสายล่าสุดได้ตลอดเวลาและไม่ต้องกังวลว่าจะพลาดการโทรกลับ
นอกจากนี้ยังช่วยให้คุณใช้สตรีมเดียวกันเพื่อผลักดันไปยัง:
project.next(5678);
//output
//Subscription Streaming: 5678
แต่ถ้าคุณแน่ใจ 100% ว่าต้องโทรเพียงครั้งเดียว? การปล่อยให้ตัวแบบเปิดและสิ่งที่สังเกตได้นั้นไม่ดี แต่มักมีคำว่า"เกิดอะไรขึ้น"
นั่นคือจุดที่AsyncSubject เข้ามา
let project = new AsyncSubject();
project.subscribe(result => console.log('Subscription Streaming:', result),
err => console.log(err),
() => console.log('Completed'));
http.get('path/to/whatever/projects/1234').subscribe(result => {
project.next(result));
project.complete();
setTimeout(() => project.subscribe(project => console.log('Delayed Sub:', project)), 2000);
});
สุดยอด! แม้ว่าเราจะปิดหัวข้อ แต่ก็ยังตอบกลับด้วยสิ่งสุดท้ายที่โหลด
อีกประการหนึ่งคือเราสมัครรับการโทร 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) {}
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({
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);
}
}
ฉันเป็นแฟนตัวยงของผู้สังเกตการณ์และผู้สังเกตการณ์ดังนั้นฉันหวังว่าการอัปเดตนี้จะช่วยได้!
คำตอบเดิม
ฉันคิดว่านี่เป็นกรณีการใช้งานของการใช้วัตถุที่สังเกตได้หรือใน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
ที่ฟังก์ชั่นบริการต่างๆของคุณสามารถผลักดันได้
หากคุณต้องการส่งคืนสิ่งที่สังเกตได้โดยตรงจากการโทรคุณสามารถทำสิ่งนี้ได้:
myHttpCall(path) {
return Observable.create(observer => {
http.get(path).map(res => res.json()).subscribe((result) => {
var newResultArray = mySpecialArrayFunction(result);
observer.next(newResultArray);
observer.complete();
});
});
}
ซึ่งจะช่วยให้คุณทำสิ่งนี้ได้ในส่วนประกอบ:
peopleService.myHttpCall('path').subscribe(people => this.people = people);
และยุ่งกับผลลัพธ์จากการโทรในบริการของคุณ
ฉันชอบสร้างEventEmitter
สตรีมด้วยตัวเองในกรณีที่ฉันต้องการเข้าถึงจากส่วนประกอบอื่น ๆ แต่ฉันเห็นทั้งสองวิธีในการทำงาน ...
นี่คือ Plunker ที่แสดงบริการพื้นฐานพร้อมตัวปล่อยเหตุการณ์: Plunkr