Tại sao setTimeout () làm cho ứng dụng của tôi bị lag, nhưng bộ đếm thời gian Rxjs (). Đăng ký (khác) thì không?


9

Tôi có một thành phần, "lười tải" một số bình luận, trong khoảng 100ms.

Khi tôi sử dụng setTimeout, nó thực sự bị lag.

thành phần

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

Điều này làm cho Ứng dụng của tôi bị lag (avg fps 14, thời gian rảnh 51100ms):

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

Điều này làm cho Ứng dụng của tôi trơn tru (avg fps 35, thời gian nhàn rỗi 40800ms)

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

Có bất kỳ giải thích, tại sao bộ đếm thời gian rxjs, hoạt động tốt hơn nhiều?

Tôi đã làm một phân tích thời gian chạy với firefox. Trong ví dụ đầu tiên, tốc độ khung hình giảm xuống 14 khung hình / giây Trong ví dụ khác, 35 khung hình / giây.

Ngay cả thời gian nhàn rỗi cũng thấp hơn 20%.

Phương pháp này thậm chí còn mượt mà hơn (avg fps 45, thời gian nhàn rỗi 13500ms):

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

Câu trả lời:


2

Giải pháp cuối cùng của bạn là cách duy nhất đúng.

Hai giải pháp khác không nên hoạt động như bạn mong đợi chúng hoạt động. Trên thực tế, điều này sẽ dẫn đến một vòng lặp vô hạn.

Điều này là do cách hoạt động của eventloop của JavaScript . Hình ảnh sau đây cho thấy một mô hình thời gian chạy JavaScript (Hình ảnh được lấy từ đây ):

nhập mô tả hình ảnh ở đây

Các phần có liên quan cho chúng tôi là stackqueue. Một thời gian chạy JavaScript xử lý các thông báo trên queue. Mỗi tin nhắn được liên kết với một chức năng được gọi là tin nhắn được xử lý.

Đối với ngăn xếp, mỗi lệnh gọi hàm tạo một khung trên ngăn xếp chứa các đối số hàm và biến cục bộ. Nếu một chức năng gọi một chức năng khác, một khung mới sẽ được đẩy lên trên cùng của ngăn xếp. Khi một hàm trả về khung trên cùng được bật ra khỏi ngăn xếp.

Bây giờ nếu ngăn xếp trống, bộ thực thi JavaScript sẽ xử lý thông báo tiếp theo trên queue(thư cũ nhất).

Nếu bạn sử dụng setTimeout(() => doSomething(),100), doSomething()chức năng sẽ được thêm vào hàng đợi sau 100 mili giây. Đây là lý do tại sao 100 mili giây không phải là thời gian được đảm bảo mà là thời gian tối thiểu. Do đó, doSomething methodchỉ được gọi của bạn , nếu ngăn xếp trống và không có gì khác trong hàng đợi.

Nhưng khi bạn lặp lại trong một vòng lặp while và điều kiện của bạn phụ thuộc vào mã bên trong setTimeout, bạn đã tạo một vòng lặp vô hạn vì ngăn xếp sẽ không trống và do đó this.posts.push(this.postService.next(10));mã của bạn sẽ không bao giờ được gọi.

Đối với các triển khai RxJS, điều tương tự là đúng. Họ sử dụng lịch trình để xử lý thời gian. Có các triển khai lập lịch trình nội bộ khác nhau trong RxJS, nhưng như chúng ta có thể thấy trong các triển khai cho intervaltimer, nếu chúng ta không chỉ định một trình lập lịch biểu thì trình mặc định là asyncScheduler. Lịch biểu asyncScheduler hoạt động với setIntervalcác hoạt động như setTimeoutđã đề cập ở trên và đẩy một thông báo khác trên hàng đợi.

Tôi đã thử hai giải pháp của bạn với vòng lặp while và thực tế là giải pháp đầu tiên hoàn toàn đóng băng trình duyệt của tôi trong khi giải pháp thứ hai siêu lag nhưng có thể xuất ra thứ gì đó cho giao diện điều khiển bên trong vòng lặp while. Tôi thực sự không biết tại sao cái thứ hai lại có hiệu suất cao hơn một chút, nhưng cả hai không phải là thứ bạn thực sự muốn. Bạn đã đưa ra một giải pháp tốt và tôi hy vọng câu trả lời này có thể giúp bạn hiểu tại sao các giải pháp đầu tiên thực hiện quá tệ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.