Angular 例外情况:尝试检测脱水检测器上的变化
下面是我的简单自定义指令,它获取并显示jsonp资产Angular 例外情况:尝试检测脱水检测器上的变化,angular,Angular,下面是我的简单自定义指令,它获取并显示jsonp资产 @Directive({ selector: 'cms', viewInjector: [httpInjectables], properties:['assets'], lifecycle:[LifecycleEvent.onDestroy] }) // We inherit from the default RouterOutlet export class cms { $
@Directive({ selector: 'cms', viewInjector: [httpInjectables],
properties:['assets'],
lifecycle:[LifecycleEvent.onDestroy]
})
// We inherit from the default RouterOutlet
export class cms {
$elemRef: any;
subscription:any;
jsonpRequest:any;
constructor(ngEl: ElementRef, jsonp:Jsonp ) {
this.$elemRef = $(ngEl.nativeElement);
this.jsonpRequest= jsonp.get("https://www.host.com?id=assetId&callback=JSONP_CALLBACK").toRx();
this.jsonpRequest.subscribe(function(data){
$(ngEl.nativeElement).html(data._body.assetID);
});
}
onDestroy(){
this.jsonpRequest.dispose();
}
}
在处理请求时,我会使用appRef.dispose()销毁引导应用程序。
我在请求完成时收到以下异常:
EXCEPTION: Attempt to detect changes on a dehydrated detector.
似乎已处理应用程序的JSONP回调会触发更改检测。由于应用程序不存在(或脱水),所以抛出异常(我猜)
在调用dispose之前,我为应用程序使用了change Detector Ref的分离功能,希望此应用程序及其子指令(此处为我的指令)不会触发更改检测。
但我想我在某个地方大错特错了
有人能解释一下如何解决这个问题吗
TL;博士:
如果释放应用程序并执行挂起的回调,我可以做些什么来避免异常?
编辑
在处理组件之前,我已通过强制分离组件及其宿主容器临时修复了该问题。例如:
@Inject(ChangeDetectorRef)
class baseComponent{
cd: ChangeDetectorRef;
constructor(cd:ChangeDetectorRef){
this.cd=cd;
}
forceDetach(){
this.cd._cd.parent.mode=DETACHED;
this.cd.detach();
}
}
并且做:
appRef.hostComponent.forceDetach();
appRef.dispose();
我知道这是一种恶作剧。等待更好的解决方案。很难说。。。你为什么要破坏这个应用程序?我认为这个错误是有道理的。如果你真的需要处理(UnLoad)应用程序,你应该在JSONP请求结束或在应用程序被部署时发现它,避免JSONP回调。考虑一个大规模的应用程序,其中模块是基于路由或散列参数动态加载和自举的。因此,如果我点击#Services/Todo1,Todo1应用程序将被加载并引导。如果我转到#服务/Todo2,我必须立即卸载Todo1应用程序,并加载和引导Todo2应用程序。如果Todo1的某些XHR请求处于挂起状态,理想情况下我应该中止它们以避免任何内存泄漏。JSONP不能被取消,所以我必须确保如果执行了回调,不会发生奇怪的事情,因为用户已经离开了…避免回调就行了。。一些方法将是好的。。。目前我正在处理可观察的…但是CD仍然被触发,导致异常…有趣。由于用户可以随时从一条路由移动到另一条路由,因此避免回调不是一种安全的方法。我认为,根据jsonp回调是否完成,避免处理应用程序是安全的。类似于:
启动回调,在某个服务(可能?)中保留一个值,指示它正在运行,这样我们就不会处理该应用。当回调结束时,更改该值以允许释放应用程序
。在我看来,angular似乎已经在为您这样做了。此错误意味着该对象不再存在于内存中,这意味着您可能不需要执行任何操作来销毁它。