Angular 2 서비스에서 관찰 가능한 항목 생성 및 반환
이것은 "모범 사례" 질문에 더 가깝습니다.선수가 : a 세명 선있다습니가수: a.Component
,aService
a 리고a.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
구독 방식으로 이 배열을 만들 수 있지만, 서비스가 그렇게 하고 그것을 사용할 수 있도록 하는 것이 더 깨끗할 것이라고 생각합니다.Component
.
어떻게 할 수 있습니까?Service
새로운 것을 창조합니다.Observable
그 배열을 포함하고, 그것을 반환합니까?
업데이트: 9/24/16 Angular 2.0 안정적
이 질문은 여전히 트래픽이 많이 발생하기 때문에 업데이트하고 싶었습니다.알파, 베타, 그리고 7 RC 후보들의 변화에 대한 광기로, 저는 SO 답변이 안정적으로 될 때까지 업데이트하는 것을 중단했습니다.
이는 제목 및 재생 제목을 사용하기에 완벽한 경우입니다.
저는 개인적으로 사용하는 것을 선호합니다.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();
하지만 이것은 많은 양이고 여러분이 그것을 하기 위해 기능이 필요하다는 것을 의미합니다.플랫맵 입력:
var myThing = http.get('path').flatMap(result1 =>
http.get('other/' + result1).flatMap(response2 =>
http.get('another/' + response2)));
달해요콤더, 더콤▁sweet.var
는 최종 http 호출에서 데이터를 가져오는 관측 가능합니다.
좋습니다. 하지만 저는 앵글2 서비스를 원합니다!
알겠습니다.
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);
}
}
저는 관찰자와 관찰 가능한 사람들의 열렬한 팬이기 때문에 이 업데이트가 도움이 되었으면 합니다!
원답
제 생각에 이것은 관찰 가능한 주제 또는 에서 사용하는 사용 사례입니다.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
다른 구성 요소에서 액세스해야 하는 경우를 대비하여 스트림을 자체적으로 실행할 수 있습니다. 하지만 두 가지 방법이 모두 작동하는 것을 볼 수 있었습니다.
다음은 이벤트 이미터가 있는 기본 서비스를 보여주는 플런커입니다. 플런커
다음은 Angular2 문서에서 관찰 가능한 항목을 만들고 사용하는 방법에 대한 예제입니다.
더 서비스
import {Injectable} from 'angular2/core'
import {Subject} from 'rxjs/Subject';
@Injectable()
export class MissionService {
private _missionAnnouncedSource = new Subject<string>();
missionAnnounced$ = this._missionAnnouncedSource.asObservable();
announceMission(mission: string) {
this._missionAnnouncedSource.next(mission)
}
}
구성 요소
import {Component} from 'angular2/core';
import {MissionService} from './mission.service';
export class MissionControlComponent {
mission: string;
constructor(private missionService: MissionService) {
missionService.missionAnnounced$.subscribe(
mission => {
this.mission = mission;
})
}
announce() {
this.missionService.announceMission('some mission name');
}
}
전체 및 작동 예제는 https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service 에서 확인할 수 있습니다.
생성된 개체가 정적이고 http를 통해 오지 않으면 다음과 같은 작업을 수행할 수 있습니다.
public fetchModel(uuid: string = undefined): Observable<string> {
if(!uuid) { //static data
return Observable.of(new TestModel()).map(o => JSON.stringify(o));
}
else {
return this.http.get("http://localhost:8080/myapp/api/model/" + uuid)
.map(res => res.text());
}
}
편집: Angular 7.x.x의 경우 여기에 설명된 대로 pipe()를 사용하여 매핑해야 합니다(https://stackoverflow.com/a/54085359/986160) :
import {of, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
[...]
public fetchModel(uuid: string = undefined): Observable<string> {
if(!uuid) { //static data
return of(new TestModel());
}
else {
return this.http.get("http://localhost:8080/myapp/api/model/" + uuid)
.pipe(map((res:any) => res)) //already contains json
}
}
관찰자 및 정적 데이터에 대한 제 질문에 대한 답변: https://stackoverflow.com/a/35219772/986160
저는 파티에 조금 늦었지만, 저의 접근 방식은 이벤트 이미터와 주제를 사용하지 않는다는 장점이 있다고 생각합니다.
제 접근법은 이렇습니다.우리는 구독()에서 벗어날 수 없고, 그러고 싶지도 않습니다.그런 맥락에서, 우리의 서비스는 반환할 것입니다.Observable<T>
우리의 소중한 화물을 가지고 있는 관찰자와 함께.호자로터초변고하기화수를부출,▁variableize,,Observable<T>
그리고 그것은 서비스의 승인을 받을 것입니다.Observable<T>
다음으로 이 개체를 구독합니다.마지막으로 서비스에서 "T"!를 얻습니다.
우선, 우리 직원들은 서비스를 제공하지만 당신의 직원들은 매개 변수를 통과하지 못합니다. 그것이 더 현실적입니다.
people(hairColor: string): Observable<People> {
this.url = "api/" + hairColor + "/people.json";
return Observable.create(observer => {
http.get(this.url)
.map(res => res.json())
.subscribe((data) => {
this._people = data
observer.next(this._people);
observer.complete();
});
});
}
좋아요, 보시다시피, 저희는 당신이 원하는 것을Observable
"사람들" 타입의.그 방법의 특징은, 심지어 그렇게 말합니다!우리는 그것을 집어넣습니다._people
우리의 관찰자에게 이의를 제기합니다.구성요소의 호출자로부터 다음 유형에 액세스합니다!
구성 요소:
private _peopleObservable: Observable<people>;
constructor(private peopleService: PeopleService){}
getPeople(hairColor:string) {
this._peopleObservable = this.peopleService.people(hairColor);
this._peopleObservable.subscribe((data) => {
this.people = data;
});
}
초기화합니다._peopleObservable
그것을 반환함으로써Observable<people>
우리의PeopleService
그런 다음 이 숙박업소에 가입합니다.드디어 저희가.this.people
우리의 자료에 (people
) 응답.
이러한 방식으로 서비스를 설계하면 일반적인 서비스인 맵(...) 및 구성 요소인 "구독(...)" 패턴보다 큰 이점이 있습니다.현실 세계에서는, 우리는 json을 우리 반에 있는 우리의 자산에 매핑해야 하고, 때때로, 우리는 그곳에서 몇 가지 맞춤형 작업을 합니다.그래서 이 매핑은 우리 서비스에서 발생할 수 있습니다.일반적으로 서비스 호출은 한 번이 아니라 코드의 다른 위치에서 사용되기 때문에 일부 구성 요소에서 매핑을 다시 수행할 필요가 없습니다.게다가 사람들에게 새로운 분야를 추가하면 어떨까요?
service.ts 파일에서 -
관찰 가능한/의 에서 'of' 가져오기
json 목록 생성
ObservableObservable.of()를 합니다.
. -예.
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
@Injectable()
export class ClientListService {
private clientList;
constructor() {
this.clientList = [
{name: 'abc', address: 'Railpar'},
{name: 'def', address: 'Railpar 2'},
{name: 'ghi', address: 'Panagarh'},
{name: 'jkl', address: 'Panagarh 2'},
];
}
getClientList () {
return Observable.of(this.clientList);
}
};
서비스의 get 함수를 호출하는 구성 요소에서 -
this.clientListService.getClientList().subscribe(res => this.clientList = res);
관찰 가능한 #map을 사용하여 원시를 변환하고 있습니다.Response
기본 관측 개체가 JSON 응답의 구문 분석된 표현으로 방출합니다.
내가 당신을 제대로 이해했다면, 당신은 원하는 것입니다.map
그 을 당신의 다시한번의 하는 것. 하이그원시을당번신다의변스로니환스합턴인지는.Model
따라서 다음과 같은 작업을 수행할 수 있습니다.
http.get('api/people.json')
.map(res => res.json())
.map(peopleData => peopleData.map(personData => new Person(personData)))
그래서, 당신은 관찰 가능한 것으로 시작했습니다.Response
객체를 해당 응답의 구문 분석된 JSON 객체를 방출하는 관측 가능한 객체로 변환한 다음 원시 JSON을 모델 배열로 변환한 또 다른 관측 가능한 객체로 변환합니다.
언급URL : https://stackoverflow.com/questions/33675155/creating-and-returning-observable-from-angular-2-service
'programing' 카테고리의 다른 글
Visual Studio 2015 및 IFormat Provider(CA1305)의 문자열 보간 (0) | 2023.05.12 |
---|---|
안드로이드 앱에 어떤 이클립스 버전을 사용해야 합니까? (0) | 2023.05.07 |
그것을 해제하는 명령이 있습니까? (0) | 2023.05.07 |
PowerShell에서 문자열과 변수를 연결하려면 어떻게 해야 합니까? (0) | 2023.05.07 |
에서 명명된 캡처 그룹에 액세스하려면 어떻게 해야 합니까?NET 정규식? (0) | 2023.05.07 |