我正在努力解决我的观点未从服务中更新的问题。
我想要实现的是消息处理。我发送消息给服务,订阅的组件得到更新。在模型上,一切都很完美,但视图根本没有变化。
我的服务:
import {Injectable} from '@angular/core';
import {Observer} from 'rxjs/Observer';
import {Subscription} from 'rxjs/Subscription';
import {Subject} from 'rxjs/Rx';
import {MyMessage} from './myMessage';
@Injectable()
export class MessageHandlingService {
private _message: Subject<MyMessage> = new Subject();
handle(message: string, stack: string) {
// console.log('handle', message, stack);
let newMyMessage: MyMessage;
if (stack) {
newMyMessage = new MyMessage(2, message, stack);
} else {
newMyMessage = new MyMessage(1, message, stack);
}
this._message.next(newMyMessage);
}
subscribeMessages(observer: Observer<MyMessage>): Subscription {
// console.log('MessageHandling - subscriber accepted');
return this._message.subscribe(observer);
}
}
我的组件:
import {Component, OnInit, OnDestroy} from '@angular/core';
import {Observer} from 'rxjs/Observer';
import {Subscription} from 'rxjs/Subscription';
import {MessageHandlingService} from './messageHandling.service';
import {MyMessage} from './myMessage';
@Component({
templateUrl: './my-messager.component.html',
selector: 'mymy-messager'
})
export class MyMessagerComponent implements OnInit, OnDestroy, Observer<MyMessage> {
private _subscription: Subscription;
display: boolean = false;
msg: MyMessage = null;
constructor(private messageHandling: MessageHandlingService) {}
ngOnInit() {
console.log('MyMessager is subscribing');
this._subscription = this.messageHandling.subscribeMessages(this);
}
ngOnDestroy() {
console.log('MyMessager is UN-subscribing');
if (this._subscription) {
this._subscription.unsubscribe();
}
}
/* istanbul ignore next */
complete() {}
/* istanbul ignore next */
error(e: any) {
if (console) {
console.error(e);
}
}
next(message: MyMessage) {
console.log('observed next', message);
this._showMessage(message);
}
private _showMessage(message: MyMessage) {
this.msg = message;
console.log('Settind display to true')
this.display = true;
}
hideDialog() {
this.msg = null;
this.display = false;
}
}
和组件HTML
{{msg}}
{{display}}
<span *ngIf="msg">
<span *ngIf="msg.severity === 1">
<p-dialog
header="Information message"
[(visible)]="display"
modal="modal"
showEffect="fade">
<p>{{msg.message}}</p>
<footer>
<div
class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
<button type="button" pButton icon="fa-close" (click)="hideDialog()" label="OK"></button>
</div>
</footer>
</p-dialog>
</span>
<span *ngIf="msg.severity === 2">
<p-dialog
header="Technical message"
[(visible)]="display"
modal="modal"
showEffect="fade">
<p>{{msg.message}}</p>
<br />
<hr />
<p style="white-space: pre;">{{msg.stackTrace}}</p>
<footer>
<div
class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
<button type="button" pButton icon="fa-close" (click)="hideDialog()" label="OK"></button>
</div>
</footer>
</p-dialog>
</span>
</span>
我试过了
ChangeDetectorRef.detectChanges()
和
ChangeDetectorRef.markForCheck()
和
ApplicationRef.tick()
甚至
NgZone run
但没有运气。相同的代码适用于Angular 2.
答案 0 :(得分:2)
在this._message.subscribe(observer);
执行期间正在创建SafeSubscriber
function SafeSubscriber(_parentSubscriber, observerOrNext, error, complete) {
_super.call(this);
this._parentSubscriber = _parentSubscriber;
var next;
var context = this;
if (isFunction_1.isFunction(observerOrNext)) {
next = observerOrNext;
}
else if (observerOrNext) {
next = observerOrNext.next;
error = observerOrNext.error;
complete = observerOrNext.complete;
if (observerOrNext !== Observer_1.empty) {
context = Object.create(observerOrNext); // this line
因此您丢失了指向当前AppComponent
实例的链接
例如,这应该对你有用
subscribeMessages(observer: Observer<MyMessage>): Subscription {
const subscriber = new Subscriber(
observer.next.bind(observer),
observer.error.bind(observer),
observer.complete.bind(observer))
return this._message.subscribe(subscriber);
}
或者你可以使用像
这样的对象const subscriber = {
next: observer.next.bind(observer),
error: observer.error.bind(observer),
complete: observer.complete.bind(observer))
}
<强> Plunker Example 强>
答案 1 :(得分:1)
这是一个this
绑定问题。如果替换
this.messageHandling.subscribeMessages(this);
通过
this.messageHandling.subscribeMessages({
next: (message) => this.next(message),
error: (error) => this.complete(error),
complete: () => this.complete()
});
请参阅a demo。
那就是说,我宁愿暴露observable,而不是让你的服务公开一个以Observer为参数的方法。这样,调用者可以在实际订阅observable之前轻松添加它想要的运算符。 Demo