2016-09-02 2 views
3

Я создал Observable.interval с 500 мс где-то в своем дереве компонентов и подписался на него. Компонент не имеет свойств ввода или вывода. Этот интервал запускает обнаружение изменений, начиная с корневого компонента каждый раз, когда он отправляет галочку. Это вызывает много накладных расходов в моем приложении, которое не требуется. Я не могу найти документацию об этом поведении.Угловой 2 RC 5 - Observable.interval триггеры Обнаружение изменений

Возможно ли отключить обнаружение изменений, вызванное этим наблюдением?

Edit: Добавление кода

Следующий код демонстрирует то, что я хочу сделать. Я помещаю интервал за пределами зоны Углового, как предложил Гюнтер, но теперь модификации в массиве не публикуются в шаблоне. Есть ли способ обновить шаблон без запуска обнаружения изменений?

import {NotificationList} from "./NotificationList"; 
import {Notification} from "./Notification"; 
import {Component, OnDestroy, ChangeDetectorRef, NgZone} from "@angular/core"; 
import { Subscription } from 'rxjs/Subscription'; 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/observable/interval'; 

class TimedNotification { 
    notification: Notification; 
    remainingTime: number; 
} 

@Component({ 
    selector: "notifications", 
    template: ` 
     <ul> 
      <li *ngFor="let notification of notifications">notification.message</li> 
     </ul> 
    ` 
}) 
export class NotificationComponent implements OnDestroy { 
    notifications: Array<TimedNotification> = []; 
    private subscription: Subscription; 
    private timer: Subscription = null; 
    private delay: number = 2000; 
    private tickDelay: number = 500; 

    constructor(notificationQueue: NotificationList, private zone: NgZone) { 
     this.subscription = notificationQueue.getObservable().subscribe(notification => this.onNotification(notification)); 
     this.zone.runOutsideAngular(() => {this.timer = Observable.interval(500).subscribe(x => this.onTimer())}); 
    } 

    private onTimer(): void { 
     if(this.notifications.length == 0) { 
      return; 
     } 
     let remainingNotifications: Array<TimedNotification> = []; 
     for(let index in this.notifications) { 
      let timedNotification = this.notifications[index]; 
      timedNotification.remainingTime -= this.tickDelay; 
      if(timedNotification.remainingTime <= 0) { 
       continue; 
      } 
      remainingNotifications.push(timedNotification); 
     } 
     this.notifications = remainingNotifications; 
    } 

    private onNotification(notification: Notification): void { 
     let timedNotification = new TimedNotification(); 
     timedNotification.notification = notification; 
     timedNotification.remainingTime = this.delay; 
     this.notifications.push(timedNotification); 
    } 

    ngOnDestroy(): void { 
     this.subscription.unsubscribe(); 
     if(this.timer !== null) { 
      this.timer.unsubscribe(); 
     } 
    } 
} 

ответ

0

Вы можете выключить его компонентов с использованием ChangeDetectionStrategy.OnPush.

Каждое событие вызывает запуск обнаружения изменений (и setTimeout и любой другой асинхронный API, который покрыт NgZone).

Если вы используете OnPush, то только изменения на входы и события от наблюдаемых подписываются на | async.

+0

Думаю, что это нужно наоборот. Я хочу, чтобы Observable не вызывал обнаружение изменений в любом другом компоненте. Этот интервал отвечает только за манипуляцию массивом, он не имеет связи с внешним. – Normalo

+0

Вы можете запустить наблюдаемую внешнюю зону углов. http://blog.thoughtram.io/angular/2016/02/01/zones-in-angular-2.html#running-code-outside-angulars-zone –

+0

Вау, это почти все. Могу ли я выполнять обнаружение изменений только для компонента, в котором создается Observable? Мне нужно будет обновить представление в случае обновления массива. – Normalo

Смежные вопросы