为啥数组的 Observable 和订阅者不起作用?
Posted
技术标签:
【中文标题】为啥数组的 Observable 和订阅者不起作用?【英文标题】:Why is the Observable and subscriber for an array not working?为什么数组的 Observable 和订阅者不起作用? 【发布时间】:2017-11-18 06:16:35 【问题描述】:我正在尝试编写一个简单的错误处理服务。它可以接收错误并将它们添加到数组中,但由于某种原因,它不起作用。
errorhandling.service
@Injectable()
export class ErrorHandlingService
private errors: Array<ErrorMessage>;
constructor()
this.errors = new Array<ErrorMessage>();
getErrors(): Observable<Array<ErrorMessage>>
return Observable.of(this.errors);
handleError(error: Response, errorText: string)
let errorMessage = this.createErrorMessage(error);
errorMessage.displayText = errorText;
this.errors.push(errorMessage);
private createErrorMessage(error: Response): ErrorMessage
let errorMessage: ErrorMessage = new ErrorMessage();
errorMessage.errorType = error.type;
errorMessage.statusCode = error.status;
return errorMessage;
export class ErrorMessage
statusCode: number;
displayText: string;
errorType: ResponseType;
app.component.ts
export class AppComponent implements OnInit
errorMessage: Message[] = [];
constructor(private authService: AuthService, private renderer: Renderer, private errorhandlingService: ErrorHandlingService)
localStorage.removeItem(AppConstants.authenticationLocalStorageKey);
ngOnInit(): void
this.errorhandlingService.getErrors().subscribe(errorMessages =>
let errorMessage: ErrorMessage = errorMessages.pop();
console.log(errorMessage);
this.errorMessage = errorMessage ? [ severity: 'error', summary: '', detail: errorMessage.displayText ] : [];
);
onDeactivate()
//scroll to top of page after routing
this.renderer.setElementProperty(document.body, "scrollTop", 0);
app.component.html
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-10 well center-text">
<p-messages [value]="errorMessage"></p-messages>
<router-outlet (deactivate)="onDeactivate()"></router-outlet>
</div>
<div class="col-md-1"></div>
</div>
下面的代码在另一个触发错误处理服务方法的组件中。
businessArea.component.ts
this.businessAreaService.getBusinessAreaById(id)
.subscribe(businessArea =>
this.model = businessArea;
,
error => this.errorHandlingService.handleError(error, 'Could not load Business Area'));
编辑:我尝试了很多类似 Observable 的东西,但效果不佳。我不确定主题是什么以及如何使用它,但似乎 Observable 在我的场景中是有意义的。任何有用的链接也会有所帮助吗?我可以断点,我可以看到它命中了方法,然后它将错误推送到数组中,但永远不会调用 app.component 上的订阅。
预期行为:
当在错误情况下调用this.businessAreaService.getBusinessAreaById
时,它会调用errorHandlingService.handleError
,后者通过调用方法this.errorHandlingService.handleError
将错误记录在errorHandlingService 的数组中。现在我在 app.component 中有一个订阅者,当错误添加到数组时应该调用它,以便我可以在 div 中显示错误。
什么不起作用: 在错误处理服务中将元素/错误添加到数组时,不会调用 app.component.ts 上的订阅者。不应该在数组触发订阅者中添加元素吗?只有在第一次调用 ngOnit 时才会调用它。在任何后续错误之后,不会调用订阅者。虽然我可以看到错误被推送到数组中。
【问题讨论】:
能否请您详细说明哪些功能不起作用以及您希望它做什么? @Raven 我已经编辑了我的问题,我不确定我还能写什么来更好地解释。你认为我的编辑有意义吗? 是的,一切正常。当我运行应用程序时,我在 console.log 中未定义,因为没有错误,但在后续调用中,它不会记录任何内容。第二次及以上时间不调用类似的订阅者 谢谢,编辑确实把事情弄清楚了。我敢肯定,您正在以错误的方式创建可观察对象以使其侦听更改。让我查一下 我很确定,我犯了一些根本性的错误。我已经阅读了很多文档,他们都建议 Observable.of 或 Observable.from...但似乎在第一次 Observable 后不会为订阅者触发。 【参考方案1】:您可以使用Subject
来实现它,如下所示更新您的服务类中的代码,您无需修改除服务类之外的任何其他内容
import Subject from 'rxjs';
@Injectable()
export class ErrorHandlingService
private errors: Array<ErrorMessage>;
private broadcaster = new Subject<Array<ErrorMessage>>();
constructor()
this.errors = new Array<ErrorMessage>();
getErrors(): Subject<Array<ErrorMessage>>
return this.broadcaster;
handleError(error: Response, errorText: string)
let errorMessage = this.createErrorMessage(error);
errorMessage.displayText = errorText;
this.errors.push(errorMessage);
// letting all subscribers know of the new change
this.broadcaster.next(this.errors);
private createErrorMessage(error: Response): ErrorMessage
let errorMessage: ErrorMessage = new ErrorMessage();
errorMessage.errorType = error.type;
errorMessage.statusCode = error.status;
return errorMessage;
export class ErrorMessage
statusCode: number;
displayText: string;
errorType: ResponseType;
【讨论】:
肯定会试试,subject 和 observable 有什么区别?抱歉,我对这些概念不熟悉 啊..我刚刚从移动设备切换到桌面来发布这个答案。请务必使用正确的 importimport Subject from '@reactivex/rxjs/es6/Subject.js'
以避免任何与 tree-shaking 相关的问题。
Subject
与Observable
相似,因为Subject
允许您订阅它以收听更新,但是Subject
s 不要t 提供 Observable
s 提供的那些运营商,您必须在 Subject
上手动调用 next
以将更改推送给订阅者
Subject
是create
函数的简单实现。要添加到此答案,使用 Observable.of
的原始实现不包含任何在流中推送新值的逻辑。这里.next()
用于将变量推入流中。
@Raven Observable
没有 next
方法以上是关于为啥数组的 Observable 和订阅者不起作用?的主要内容,如果未能解决你的问题,请参考以下文章
来自数组的 Observable 在 TypeScript 中不起作用