Neden setTimeout () uygulamamı laggy yapıyor, ama Rxjs timer (). Abone ol (…) yapmıyor?


9

Ben 100 ms aralıklarla, bazı yorumlar "tembel yükler" bir bileşeni var.

SetTimeout'u kullandığımda gerçekten laggy.

bileşen

<div *ngFor="let post of posts">
   <app-post [post]="post" ></app-post>
</div>

Bu benim Uygulama laggy yapar (avg fps 14, boşta kalma süresi 51100ms):

while(this.postService.hasPosts()){
  setTimeout(()=> {
   this.posts.push(this.postService.next(10));
  },100);
}

Bu, Uygulamamı pürüzsüz hale getirir (avg fps 35, boşta kalma süresi 40800ms)

while(this.postService.hasPosts()){
  timer(100).subscribe(()=> {
    this.posts.push(this.postService.next(10));
  });
}

Herhangi bir açıklama var, neden rxjs zamanlayıcı, çok daha iyi çalışıyor?

Firefox ile bir çalışma zamanı analizi yaptım. İlk örnekte, kare hızı 14 fps'ye düşer. Diğer örnekte 35 fps'dir.

Boşta kalma süresi bile% 20 daha düşüktür.

Bu yöntem daha da yumuşaktır (avg fps 45, boşta kalma süresi 13500ms):

interval(100).pipe(takeWhile(this.postService.hasPosts()).subscribe(()=> {
    this.posts.push(this.postService.next(10));
  });
}

Yanıtlar:


2

Son çözümünüz tek doğru çözümdür.

Diğer iki çözüm de beklediğiniz gibi çalışmamalıdır. Aslında, bu sonsuz bir döngüye neden olmalıdır.

Bunun nedeni JavaScript'in olay döngüsünün nasıl çalıştığıdır. Aşağıdaki resim JavaScript çalışma zamanının bir modelini göstermektedir (Görüntü buradan alınmıştır ):

resim açıklamasını buraya girin

Bizim için ilgili parçalar stackve queue. Bir JavaScript çalışma zamanı, üzerindeki iletileri işler queue. Her mesaj, mesaj işlenirken çağrılan bir fonksiyonla ilişkilendirilir.

Yığın için, her işlev çağrısı yığın üzerinde işlev bağımsız değişkenlerini ve yerel değişkenleri içeren bir çerçeve oluşturur. Bir işlev başka bir işlevi çağırırsa, yığının üstüne yeni bir çerçeve itilir. Bir işlev döndüğünde üst çerçeve yığından çıkar.

Yığın boşsa, JavaScript çalışma zamanı queue(en eskisi) bir sonraki mesajı işleyecektir .

Kullanırsanız setTimeout(() => doSomething(),100), doSomething()işlev 100 milisaniyeden sonra kuyruğa eklenir. 100 milisaniyenin garanti edilen bir zaman değil, minimum bir zaman olmasının nedeni budur. Bu nedenle doSomething method, yığın boşsa ve sırada başka bir şey yoksa, yalnızca aranır.

Ancak bir while döngüsünde yineleme yaptığınız ve durumunuz içindeki koda bağlı setTimeoutolduğundan, yığın boşalmayacağından sonsuz bir döngü oluşturdunuz ve bu nedenle this.posts.push(this.postService.next(10));kodunuz asla çağrılmayacaktır.

RxJS uygulamaları için aynı şey geçerlidir. Zamanlamayı işlemek için zamanlayıcılar kullanırlar. RxJS'de farklı dahili zamanlayıcı uygulamaları vardır, ancak uygulamalarda görebildiğimiz gibi intervalve timerbir zamanlayıcı belirtmezsek, varsayılan olan asyncScheduler'dir. AsyncScheduler zamanlamaları yukarıda belirtildiği gibi setIntervalçalışır setTimeoutve kuyruğa başka bir ileti gönderir.

While döngüsüyle iki çözümünüzü denedim ve ikincisi süper laggy iken aslında birincisi tarayıcımı tamamen dondu, ancak while döngüsünün içindeki konsola bir şeyler çıktı. Aslında ikincisinin neden biraz daha performans gösterdiğini bilmiyorum, ama yine de her ikisi de aslında istediğiniz şey değil. Zaten iyi bir çözüm buldunuz ve umarım bu cevap ilk çözümlerin neden bu kadar kötü performans gösterdiğini anlamanıza yardımcı olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.