2017-11-16 4 views
1

일부 대기 메시지를 표시하거나 숨기려면 비동기 파이프를 사용해 봅니다. app.component.html비동기 파이프 (각도)와 혼동 된 동작

<ng-template #isWait> 
    <h1>Please wait</h1> 
</ng-template> 

<div *ngIf="wait | async; else isWait"> 
    <hello name="{{ name }}"></hello> 

    <p> 
     Start editing to see some magic happen :) 
    </p> 

</div> 

<button (click)="toggle()">Toggle</button> 

<!-- Doesn't change --> 
<div style="margin:1rem;"> 
    Doesn't change here 
    <span style="color:red;">Value is {{wait | async}}</span> 
    (AppComponent) 
</div> 

이 app.component.ts

@Component({ 
    selector: 'my-app', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css'] 
}) 
export class AppComponent { 
    name: string = 'Angular 5'; 
    wait: Observable<boolean>; 

    constructor(public waitService: WaitService) { 
    this.wait = this.waitService.wait; 
    } 

    toggle() { 
    this.waitService.toggle(); 
    } 
} 

wait.service.ts

export class WaitService { 
    wait: Observable<boolean>; 
    private _wait: boolean = false; 
    private _onChange: EventEmitter<boolean> = new EventEmitter(); 

    constructor() { 
    this.wait = Observable.create((obs: any) => { 
     obs.next(this._wait); 
     this._onChange.subscribe((w: boolean) => { 
     if (this._wait !== w) { 
      this._wait = w; 
      obs.next(this._wait); 
     } 
     }); 
    }); 
    } 

    toggle() { 
    this._onChange.emit(!this._wait); 
    } 
} 

내가 대기와 WaitService이 속성 및 방법 전환 대기를 위해을 토글합니다. 으로 토글하려고 할 때 하나의 경우에는 작동하지만, 예상 한대로 서로 작동하지는 않습니다.

그래서 혼란 스러웠습니다. 나는 그 이유를 알아낼 것입니다.

예 : https://stackblitz.com/edit/angular-fwghfj

당신이 방출됩니다 Wait2Component에 토글 버튼 대기 메시지와 함께 일어날 아무것도하지만, 가입을 클릭하고 토글을 클릭하면 출력마다 콘솔에 쓸 수됩니다.

하지만 가입 대기열이 표시된 후에는 대기 및 숨기기 대기 메시지가 작동하지만 다른 곳에서는 대기은 변경 사항이 없습니다.

물론 나는 부울 할 기다린 비동기 이 상황,하지만 나를 위해이 예기치 않은 동작이 걱정하지 않는다 변경할 수 있습니다.

답변

0

이 대신 같은 WaitService을 작성할 수 있습니다

import { Injectable } from "@angular/core"; 
import { BehaviorSubject } from "rxjs/BehaviorSubject"; 

@Injectable() 
export class WaitService 
{ 
    private readonly isWaiting = new BehaviorSubject(false); 
    public readonly wait$ = this.isWaiting.asObservable(); 
    public toggle() 
    { 
     this.isWaiting.next(!this.isWaiting.value); 
    } 
} 
+0

파벨 한 장소에서 juste 변경하는 경우 당신은, 당신이 그렇지 않으면 사방

을 변경해야합니다 귀하의 재산의 이름을 변경하려면 더 명확하고 아름다운 코드를 주셔서 감사합니다! –

1

문제는 각 가입자에 대한 Observable.create에 대한 콜백이 호출 될 것입니다 그리고 당신이 this._wait의 상태를 수정 장소입니다. 즉, toggle()으로 전화하면 this._onChange.subscribe()next 핸들이 호출됩니다. 5 배 또는 어쩌면 더. 그러나 첫번째 호출 만이 this._wait !== w 때문에 관찰자에게 알립니다.

이것을 피하는 간단한 방법은 share() 연산자와 동일한 소스 Observable을 공유하는 것입니다.

this.wait = Observable.create((obs: any) => { 
    // ... 
}).share(); 

하지만 더 나은 솔루션 Observable.create 내부 subscribe() 호출 단지 부작용 수행 do()와 조작자 체인을 사용하지 않는 것 :이 동일한 결과를 산출한다

this.wait = this._onChange 
    .filter((w: boolean) => w !== this._wait) 
    .do((w: boolean) => this._wait = w) 
    .share(); 

. https://stackblitz.com/edit/angular-nbgmz7?file=app%2Fservices%2Fwait.service.ts

+0

마틴, 당신의 도움과 상세한 설명에 큰 감사드립니다. rxjs의 작동 방식을 더 연습하고 이해해야하므로 이해합니다. –

0

app.component :

당신에게 업데이트 된 데모를 참조하십시오.그것은 공공 넣어보다 TS

@Component({ 
    selector: 'my-app', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css'] 
}) 
export class AppComponent { 
    name: string = 'Angular 5'; 
    wait: Observable<boolean>; 

    constructor(public waitService: WaitService) { 
    this.wait = this.waitService.waitingStatus(); 
    } 

    toggle() { 
    this.waitService.toggle(); 
    } 
} 

서비스

@Injectable() 
export class WaitService { 
    private currentWaitingStatus: boolean = false; 
    private waitingStatus$: Subject<boolean> = new BehaviorSubject<boolean>(this.currentWaitingStatus) 

    waitingStatus(): Observable<boolean> { 
    return this.waitingStatus$ 
    } 

    toggle() { 
    this.currentWaitingStatus= !this.currentWaitingStatus 
    this.waitingStatus$.next(this.currentWaitingStatus) 
    } 
} 

나는 내 재산을 반환하는 방법을 선호한다.

구성 요소는 서비스의 내부 상태를 알 수 없으므로 서비스가 사용 N 클라이언트, 내일이면 당신은 추상적이 방법 뒤에 당신이 당신의 서비스