Ответ 1
Единственное решение, которое сработало для меня, было:
if (!this.changeDetectionRef['destroyed']) {
this.changeDetectionRef.detectChanges();
}
Я создаю простой пользовательский интерфейс, используя Angular Meteor 2.
1) У меня есть верхний элемент навигации, который имеет кнопку "Выход".
2) При нажатии кнопки "Выход" она перенаправляется на "login".
3) Затем я вижу эту ошибку в консоли: EXCEPTION: Attempt to use a destroyed view: detectChanges
Исключение:
EXCEPTION: Attempt to use a destroyed view: detectChanges
browser_adapter.js:77 EXCEPTION: Attempt to use a destroyed view: detectChangesBrowserDomAdapter.logError @ browser_adapter.js:77BrowserDomAdapter.logGroup @ browser_adapter.js:87ExceptionHandler.call @ exception_handler.js:57(anonymous function) @ application_ref.js:265schedulerFn @ async.js:123SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:112onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:66ZoneDelegate.handleError @ angular2-polyfills.js:394Zone.runTask @ angular2-polyfills.js:323ZoneTask.invoke @ angular2-polyfills.js:490
browser_adapter.js:77 STACKTRACE:BrowserDomAdapter.logError @ browser_adapter.js:77ExceptionHandler.call @ exception_handler.js:59(anonymous function) @ application_ref.js:265schedulerFn @ async.js:123SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:112onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:66ZoneDelegate.handleError @ angular2-polyfills.js:394Zone.runTask @ angular2-polyfills.js:323ZoneTask.invoke @ angular2-polyfills.js:490
browser_adapter.js:77 Error: Attempt to use a destroyed view: detectChanges
at ViewDestroyedException.BaseException [as constructor] (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:3349:23)
at new ViewDestroyedException (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:10626:16)
at DebugAppView.AppView.throwDestroyedError (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:11277:72)
at DebugAppView.AppView.detectChanges (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:11230:18)
at DebugAppView.detectChanges (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:11321:44)
at ViewRef_.detectChanges (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:11011:65)
at http://localhost:3000/app/app.js?hash=323b1216814e80ed467d95bcda255eb217d7c468:2224:23
at ZoneDelegate.invokeTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4721:174)
at Object.onInvokeTask (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:9393:41)
at ZoneDelegate.invokeTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4721:72)
------------- Elapsed: 80 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMacroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4652:47)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4467:37
at setTimeout (eval at createNamedFn (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5346:24), <anonymous>:3:37)
at new TopNavbarComponent (http://localhost:3000/app/app.js?hash=323b1216814e80ed467d95bcda255eb217d7c468:2221:9)
at DebugAppView._View_HomeComponent0.createInternal (HomeComponent.template.js:48:34)
at DebugAppView.AppView.create (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:11098:21)
------------- Elapsed: 2 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at resolvePromise (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4893:29)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4930:25
at ZoneDelegate.invokeTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4721:174)
at Object.onInvokeTask (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:9393:41)
------------- Elapsed: 0 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at ZoneAwarePromise.then (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5011:25)
at RuntimeCompiler.resolveComponent (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:40230:14)
at DynamicComponentLoader_.loadNextToLocation (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:10788:31)
at RouterOutlet.activate (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:26844:26)
------------- Elapsed: 0 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at resolvePromise (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4893:29)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4877:21
at ZoneDelegate.invoke (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4696:161)
at Object.onInvoke (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:9402:41)
------------- Elapsed: 0 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at resolvePromise (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4893:29)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4877:21
at ZoneDelegate.invoke (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4696:161)
at Object.onInvoke (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:9402:41)
------------- Elapsed: 0 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at resolvePromise (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4893:29)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4930:25
at ZoneDelegate.invokeTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4721:174)
at Object.onInvokeTask (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:9393:41)
------------- Elapsed: 1 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at ZoneAwarePromise.then (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5011:25)
at http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:26895:53
at http://localhost:3000/packages/meteor.js?hash=ae8b8affa9680bf9720bd8f7fa112f13a62f71c3:1105:22
at ZoneDelegate.invoke (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4696:161)
------------- Elapsed: 0 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at resolvePromise (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4893:29)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4877:21
at http://localhost:3000/packages/meteor.js?hash=ae8b8affa9680bf9720bd8f7fa112f13a62f71c3:1105:22BrowserDomAdapter.logError @ browser_adapter.js:77ExceptionHandler.call @ exception_handler.js:60(anonymous function) @ application_ref.js:265schedulerFn @ async.js:123SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:112onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:66ZoneDelegate.handleError @ angular2-polyfills.js:394Zone.runTask @ angular2-polyfills.js:323ZoneTask.invoke @ angular2-polyfills.js:490
Subscriber.js:229 Uncaught Attempt to use a destroyed view: detectChanges
топ-navbar.component.ts
"use strict";
import {Logger} from "../services/logger.service";
import {Component, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core';
import {User} from "../models/user";
import {Router} from '@angular/router-deprecated';
import {UserService} from "../services/user.service";
import {CORE_DIRECTIVES} from '@angular/common';
import {DROPDOWN_DIRECTIVES} from '../../node_modules/ng2-bootstrap';
@Component({
selector: 'top-navbar',
templateUrl: 'client/top-navbar/top-navbar.html',
bindings: [UserService, Logger],
directives: [CORE_DIRECTIVES, DROPDOWN_DIRECTIVES]
})
export class TopNavbarComponent {
public user:User;
public statusDropdown = {
isOpen: false
};
constructor(private userService:UserService, private router:Router, private logger:Logger, private ref:ChangeDetectorRef) {
setTimeout(() => {
this.ref.markForCheck();
this.user = this.userService.getLoggedInUser();
this.ref.detectChanges();
}, 0)
}
logout() {
this.logger.warn('[Top Navbar] Logging out the user.');
localStorage.clear();
this.router.navigateByUrl('/login');
}
}
и это мой login.component.ts
"use strict";
import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { FormBuilder, ControlGroup, Validators } from '@angular/common';
import { MeteorComponent } from 'angular2-meteor';
import { Router } from '@angular/router-deprecated';
import { Logger } from "../services/logger.service";
@Component({
selector: 'login',
templateUrl: 'client/login/login.html',
changeDetection: ChangeDetectionStrategy.OnPush,
bindings: [Logger]
})
export class LoginComponent extends MeteorComponent {
loginForm:ControlGroup;
loginFailed = false;
constructor(private _logger:Logger, private _router:Router, private ref:ChangeDetectorRef) {
super();
let fb = new FormBuilder();
this.loginForm = fb.group({
username: ["", Validators.required],
password: ["", Validators.required]
});
}
login() {
this.call('authenticateUser', this.loginForm.value.username, this.loginForm.value.password, (err, data) => {
if (err) {
this._logger.error(err);
} else {
this._logger.info('[Authentication API] ', data);
if (data.status != 'LOGIN_SUCCESS') {
this.loginFailed = true;
} else {
this.loginFailed = false ;
var user = {
id: data.id,
name: data.name,
role: data.role
}
localStorage.setItem('user', JSON.stringify(user));
this._router.navigate(['Home'])
}
//This is required for letting Angular know that something has changed.
//Because this part of code runs out of Angular zone.
this.ref.markForCheck(); // Mark this component and its children for change detection in next detecting cycle.
this.ref.detectChanges(); // Trigger change detection.
}
});
}
}
Единственное решение, которое сработало для меня, было:
if (!this.changeDetectionRef['destroyed']) {
this.changeDetectionRef.detectChanges();
}
Я решил ту же проблему, но с помощью кода меньшего размера, я расскажу вам о том, что может помочь вам решить проблему.
Эта проблема явно возникает при detectChanges()
потому что изменения были сделаны, а метод вызван на этапе уничтожения компонента.
Таким образом, вам нужно сделать так, чтобы ваш компонент implements OnDestroy
, затем вам нужно отменить изменения, которые вызывают this.ref.detectChanges()
для this.ref.detectChanges()
. поэтому ваш TopNavbarComponent
должен быть похож на:
export class TopNavbarComponent implements OnDestroy {
// ... your code
ngOnDestroy() {
this.cdRef.detach(); // do this
// for me I was detect changes inside "subscribe" so was enough for me to just unsubscribe;
// this.authObserver.unsubscribe();
}
}
PS: Не забудьте unsubscribe()
всех наблюдателей, которые есть в вашем компоненте! В любом случае вы должны сделать это, подписка без отписки может быть основной причиной сотен проблем, включая эту, см. Angular/RxJs. Когда мне следует отписаться от "Подписки"?
Изменить: я знаю другое решение в Интернете, пытающееся просто решить проблему, обрабатывая саму ошибку, в то время как лучшая практика состоит в том, чтобы узнать корень проблемы, проверить, является ли представление уничтоженным или нет, является хорошим решением, но первоначальной причиной Это может быть причиной утечки памяти, поэтому корень проблемы в том, что работающий сервис необходимо уничтожить, НЕ просто пытаться уничтожить саму ошибку без рута, например, закрытые подписки (особенно пользовательские) должны быть закрыты.
Так что хозяйственные вещи необходимы для лучшей производительности, это не всегда более простое и быстрое решение, лучше, если вы прячете грязь под коврами, это не значит, что вы убрали свою комнату :)
Вы можете использовать
this.cdref.markForCheck();
вместо
this.cdref.detectChanges();
во многих случаях. Но лучше всего следовать рекомендациям @Al-Mothafar
Вы должны получить значение подписчика в переменной и отказаться от подписки на тот же var. Пожалуйста, обратитесь к этому же коду
import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, OnDestroy } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import { Cartservice } from './../cartservice.service';
import { ISubscription } from 'rxjs/Subscription';
export class CartComponent implements OnInit, OnDestroy {
private subscription: ISubscription;
ngOnInit() {
this.subscription = this.cartservice.productsObservable.subscribe(cart => {
this.cartProducts = cart.products;
this.cartTotal = cart.cartTotal;
this.changeDetectorRef.detectChanges();
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Обратите внимание, что у меня есть отмена изменений в методе ngOnDestroy().
Моим решением было отписаться от всех наблюдателей.
Подписка:
ngOnInit() {
this._currentUserSubscription = this._auth.currentUser.subscribe(currentUser => {});
}
Отмените подписку с помощью changeDetector.detach():
ngOnDestroy() {
this._currentUserSubscription.unsubscribe();
this._cdRef.detach();
}
Это было необходимо в моем коде, я также должен использовать функциональность ChangeDetectorRef, только те две вещи, которые мой код без ошибок.
Я решил это с:
if (!(<ViewRef>this.cd).destroyed) {
this.cd.detectChanges();
}
В моем случае это было неправильное использование асинхронной тестовой установки конфигурации компонентов и компиляции.
Ошибки, вызывающие код.
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
BrowserAnimationsModule
],
providers: [
{ provide: ComponentFixtureAutoDetect, useValue: true },
{ provide: OptionsService, useValue: optionServiceMock },
],
declarations: [EventLogFilterComponent],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
fixture = TestBed.createComponent(EventLogFilterComponent);
component = fixture.componentInstance;
optionsService = TestBed.get(OptionsService);
component.filterElem = jasmine.createSpyObj('filterElem', ['close']);
fixture.detectChanges();
});
Исправлено с...
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
BrowserAnimationsModule
],
providers: [
{ provide: ComponentFixtureAutoDetect, useValue: true },
{ provide: OptionsService, useValue: optionServiceMock },
],
declarations: [EventLogFilterComponent],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EventLogFilterComponent);
component = fixture.componentInstance;
optionsService = TestBed.get(OptionsService);
component.filterElem = jasmine.createSpyObj('filterElem', ['close']);
fixture.detectChanges();
});
Просто отсоедините ChangeDetectorRef на хуке жизненного цикла OnDestroy и проверьте, уничтожен ли ChangeDetectorRef перед выполнением метода deteChanges
constructor(private cd: ChangeDetectorRef){}
someFunction(){
if(!this.cd['destroyed']){
this.cd.detectChanges();
}
}
ngOnDestroy(){
this.cd.detach();
}
Не сильно связанный с конкретным вопросом, но я попал сюда, найдя ту же ошибку, поэтому поделюсь своим решением. Проблема заключалась в том, что я вызывал fixture.detectChanges()
внутри fixture.whenStable().then(() => {})
не заключая тест в async
функцию.
До:
it('should...', () => {
fixture.whenStable().then(() => {
fixture.detectChanges();
});
});
После:
it('should...', async(() => {
fixture.whenStable().then(() => {
fixture.detectChanges();
});
}));
Ну, эти ответы не помогли мне. Я нашел другое решение.
Дочерний компонент имеет вывод, который срабатывает при нажатии кнопки закрытия
<child-component
*ngIf="childComponentIsShown"
(formCloseEmitter)="hideChildComponent()"
></child-component>
И метод hideChildComponent() в родительском компоненте обнаруживает изменения.
hideChildComponent() {
this.childComponentIsShown = false;
this.cdr.detectChanges();
}
Надеюсь, это кому-нибудь поможет.
Просто:
import { OnDestroy } from '@angular/core';
import { Subject } from 'rxjs/Subject';
export class Component implements OnDestroy {
componentDestroyed: Subject<boolean> = new Subject();
constructor() { }
function() {
this.service.serviceFunction
.takeUntil(this.componentDestroyed)
.subscribe((incomingObservable: Type) => {
this.variable = incomingObservable;
});
}
ngOnDestroy() {
this._cdRef.detach(); //If you use change dectector
this.componentDestroyed.next(true);
this.componentDestroyed.complete();
}
Моя причина произошла, когда я пытался открыть модальное диалоговое окно с NgbActiveModal. Видимо, вызов .dismiss()
из собственного ngOnInit()
вызывает это.
export class MyModal {
constructor(private modalInstance: NgbActiveModal) {
}
ngOnInit() {
if (foo) this.modalInstance.dismiss();
}
Решением было подождать до увольнения.
if (foo) setTimeout(() => this.modalInstance.dismiss());
Для меня единственным решением, которое сработало, является следующее:
ngOnInit() {
if (this.destroyedComponent) this.changeDetector.reattach();
this.destroyedComponent = false;
this.subscription = this.reactive.channel$.subscribe(msg => {
switch (msg) {
case "config:new_data":
if (!this.destroyedComponent) {
this.table.initTable();
this.changeDetector.detectChanges();
}
}
})
}
ngOnDestroy() {
this.subscription = null;
this.destroyedComponent = true;
this.changeDetector.detach();
}
Объяснение:
Чтобы избежать этой ошибки, вместо того, чтобы вызывать detectChanges(), попробуйте обернуть код, изменяющий модель:
this.ngZone.run(() => {
...
});