2

샘플 애플 리케이션을 쓰고 있는데 사용자 목록 구성 요소가 있습니다.

@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이 어떻게 알릴 수 있는지도 모르겠습니다.


  • 간단한 팁 : ' 비공개 ' 생성자에서 클래스의 서비스 매개 변수를 private 변수로 만듭니다. 새 매개 변수에 할당 할 필요가 없습니다. - Toshkata Tonev

2 답변


1

당신이 사용할 수있는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);


1

이것은 내 라이브러리 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>

관련된 질문

최근 질문