与异步管道混淆的行为(Angular)
Confused behavior with async pipe (Angular)
我会尝试使用异步管道 show/hide 一些等待消息。
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 with wait 属性 和方法 toggle 用于切换等待。
当我尝试切换 wait 时,它在一种情况下有效,但对其他情况无效(如我所料)。
所以,这让我很困惑。
我会试着弄清楚为什么会这样。
示例:https://stackblitz.com/edit/angular-fwghfj
如果您单击“切换”按钮,等待消息不会发生任何变化,但会发出 Wait2Component 中的订阅,并且每次您单击“切换”时都会将其写入控制台输出。
但是在订阅注释行后,显示和隐藏等待消息会正常工作,但在其他地方等待仍然没有变化。
当然我可以将 wait 更改为布尔值并且不关心 async 的这种情况,但这对我来说是意想不到的行为。
您可以这样编写 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);
}
}
问题在于,对于每个订阅者,都会调用 Observable.create
的回调,这就是您修改 this._wait
状态的地方。换句话说,当您调用 toggle()
时,this._onChange.subscribe()
的 next
句柄被调用,例如。五次甚至更多。但是只有第一个调用会通知它的观察者,因为 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
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)
}
}
我更喜欢 return 我 属性 的方法而不是 public.
因为,你的组件肯定不知道你的service里面怎么样。如果你的服务被 n 个客户使用,明天你想更改你的名称 属性 你必须在所有地方都更改它
否则,如果您将其抽象为一种方法,您会在服务的某个位置更改 juste
我会尝试使用异步管道 show/hide 一些等待消息。
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 with wait 属性 和方法 toggle 用于切换等待。 当我尝试切换 wait 时,它在一种情况下有效,但对其他情况无效(如我所料)。
所以,这让我很困惑。 我会试着弄清楚为什么会这样。
示例:https://stackblitz.com/edit/angular-fwghfj
如果您单击“切换”按钮,等待消息不会发生任何变化,但会发出 Wait2Component 中的订阅,并且每次您单击“切换”时都会将其写入控制台输出。
但是在订阅注释行后,显示和隐藏等待消息会正常工作,但在其他地方等待仍然没有变化。
当然我可以将 wait 更改为布尔值并且不关心 async 的这种情况,但这对我来说是意想不到的行为。
您可以这样编写 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);
}
}
问题在于,对于每个订阅者,都会调用 Observable.create
的回调,这就是您修改 this._wait
状态的地方。换句话说,当您调用 toggle()
时,this._onChange.subscribe()
的 next
句柄被调用,例如。五次甚至更多。但是只有第一个调用会通知它的观察者,因为 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
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)
}
}
我更喜欢 return 我 属性 的方法而不是 public.
因为,你的组件肯定不知道你的service里面怎么样。如果你的服务被 n 个客户使用,明天你想更改你的名称 属性 你必须在所有地方都更改它
否则,如果您将其抽象为一种方法,您会在服务的某个位置更改 juste