샘플 애플 리케이션을 쓰고 있는데 사용자 목록 구성 요소가 있습니다.
@Component({ selector: 'user-list', templateUrl: './list.component.html', styleUrls: ['./list.component.css'], }) export class ListComponent implements OnInit { users: Array = []; private usersService: UsersService; constructor(private service: UsersService) { this.usersService = service; } loadUsers() { this.usersService.getUsers().subscribe(users => this.users = users); } ngOnInit() { this.loadUsers(); this.usersService.userEvent.subscribe(user => this.loadUsers()); } }
그리고 그 서비스는 :
@Injectable() export class UsersService { userEvent: EventEmitter = new EventEmitter(); constructor(private http: Http) { } getUsers(): Observable { return this.http.get('/rest/users') .map(res => res.json()); } create(user: User) { this.http.post("/rest/users", user).subscribe(resp => this.userEvent.emit(user)); } } export class User { constructor(public username: string, public email: string, public password: string ) { } }
그리고 사용자 생성을위한 형제 구성 요소가 있습니다.
@Component({ selector: 'app-form', templateUrl: './form.component.html', styleUrls: ['./form.component.css'] }) export class FormComponent implements OnInit { private usersService: UsersService; constructor(private service: UsersService, private router: Router) { this.usersService = service; } ngOnInit() { } onSubmit(formValue: any) { let user = new User(formValue.username, formValue.email, formValue.password); this.usersService.create(user); this.router.navigate(['users']); } }
이것은 현재 내가하고 싶은 일을하지만, 새로운 사용자가 형제 컴포넌트에 의해 서버 상에 생성되는 경우에 사용자 목록을 업데이트하는 좀 더 우아한 방법이 있는지 궁금합니다. 내가 사용자 목록을 구독하는 경우 이벤트 이미 터를 사용하여 신호를 보내는 것은 이상한 것처럼 보입니다. 서버에서 생성되는 새 사용자에 대해 http.get이 어떻게 알릴 수 있는지도 모르겠습니다.
당신이 사용할 수있는BehaviorSubject
구독하는 모든 구성 요소에 알립니다. 그것은 특별한 유형의 관측 가능합니다. 예를 들어 사용자 서비스에서 사용자를 정의하십시오 (사용자 목록으로 쉽게 변경할 수 있음).
import {Observable, BehaviorSubject} from 'rxjs/Rx'; //
import {User} from "../../models/user"; // Your model
... inside your class:
private _currentUser = new BehaviorSubject<User>(new User);
getUser = this._currentUser.asObservable();
setUser(user: User) { this._currentUser.next(user) }
구성 요소에서 구독 할 수 있습니다.getUser
주제는 다음과 같습니다.
this.userService.getUser.subscribe(
user => {
this.user = user;
});
이렇게하면 여러 구성 요소가이 구성에 가입 할 수 있습니다.BehaviorSubject
, 사용하는 구성 요소 / 서비스의 모든 트리거setUser
메서드는 이러한 가입 된 구성 요소를 즉시 변경할 수 있습니다.
... you successfully added a user in your
... component, now use the trigger:
this.userService.setUser(this.user);
이것은 내 라이브러리 RxCache가 관리하도록 설계된 것과 정확히 일치합니다. 관찰 가능한 모든 구독을 처리하므로 구독을 관리하거나 가입 누설에 대해 걱정할 필요가 없습니다.
https://github.com/adriandavidbrand/ngx-rxcache
구성 요소에서 사용자의 관찰 가능 항목과로드 플래그를 노출 할 수 있습니다.
@Component({
selector: 'user-list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.css'],
})
export class ListComponent implements OnInit {
users$ = this.service.users$;
loading$ = this.service.loading$;
constructor(private service: UsersService) {
service.load();
}
}
HTML에서 비동기 파이프를 사용하여 모든 구독 관리
<div *ngIf="loading$ | async else elseBlock">loading ...</div>
<ng-template #elseBlock>
<div *ngIf="users$ | async as users">
<div *ngFor="let user of users">
Email: {{user.email}}
</div>
</div>
</ng-template>
서비스에서 "npm install ngx-rxcache --save"를 설치하고 RxCacheService를 'ngx-rxcache'에서 가져옴으로써 RxCache를 사용하십시오.
@Injectable()
export class UsersService {
constructor(private http: Http, private cache: RxCacheService) { }
private userCache = this.cache.get<User[]>({
id: '[User] users',
construct: () => this.http.get<User[]>('/rest/users'),
save: user => this.http.post<User[]>("/rest/users", user)
});
users$ = this.userCache.value$;
loading$ = this.userCache.loading$;
saving$ = this.userCache.saving$;
create(user: User, saved?: (response: any, value: any) => void) {
this.userCache.save(user, saved);
}
load() {
this.userCache.load();
}
}
// Use interfaces over classes
export interface User {
username: string;
email: string;
password: string;
}
그리고 형제 구성 요소
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit {
constructor(private service: UsersService, private router: Router) { }
saving$ = this.service.saving$;
ngOnInit() {
}
onSubmit(formValue: any) {
let user = { username: formValue.username, email: formValue.email, password: formValue.password };
this.usersService.create(user, (response, value) => {
// Don't navigate until the save has finished.
this.router.navigate(['users']);
});
}
}
그리고 html에서는 다른 구성 요소에서로드 한 것과 같은 절약 메시지를 표시 할 수 있습니다.
<div *ngIf="saving$ | async">saving ...</div>