なぜsetTimeout()はアプリを遅延させますが、Rxjs timer()。subscribe(…)は遅延させないのですか?


9

100ms間隔でコメントを「遅延読み込み」するコンポーネントがあります。

setTimeoutを使用すると、実際に遅延します。

成分

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

これにより、アプリケーションが遅くなります(平均fps 14、アイドル時間51100ms):

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

これにより、アプリケーションがスムーズになります(平均fps 35、アイドル時間40800ms)

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

説明はありますか、なぜrxjsタイマーがはるかにうまく機能するのですか?

私はFirefoxでランタイム分析を行いました。最初の例では、フレームレートは14 fpsに下がります。他の例では、35 fpsになります。

アイドル時間も20%短くなります。

この方法はさらにスムーズです(平均fps 45、アイドル時間13500ms):

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

回答:


2

あなたの最後の解決策は唯一の正しい解決策です。

他の2つのソリューションは、期待どおりに機能しないはずです。実際には、これは無限ループになるはずです。

これは、JavaScriptのイベントループがどのように機能するかによるものです。次の図は、JavaScriptランタイムのモデルを示しています(画像はここから取得されました)。

ここに画像の説明を入力してください

私たちのために関連する部分があるstackqueue。JavaScriptランタイムは、queue。各メッセージは、メッセージが処理されるときに呼び出される関数に関連付けられています。

スタックの場合、各関数呼び出しにより、関数の引数とローカル変数を含むフレームがスタックに作成されます。関数が別の関数を呼び出すと、新しいフレームがスタックの一番上にプッシュされます。関数が戻ると、一番上のフレームがスタックからポップされます。

スタックが空の場合、JavaScriptランタイムはqueue(最も古い)の次のメッセージを処理します。

を使用するsetTimeout(() => doSomething(),100)と、doSomething()関数は100ミリ秒後にキューに追加されます。これが、100ミリ秒が保証時間ではなく最小時間である理由です。したがってdoSomething method、スタックが空で他にキューに何もない場合、あなただけが呼び出されます。

しかし、whileループで反復していて、条件が内のコードに依存しているsetTimeoutため、スタックが空にならず、this.posts.push(this.postService.next(10));コードが呼び出されないため、無限ループが作成されています。

RxJSの実装についても同様です。スケジューラを使用してタイミングを処理します。RxJSにはさまざまな内部スケジューラー実装がありますが、intervalおよびの実装でわかるtimerように、スケジューラーを指定しない場合、デフォルトのスケジューラーはasyncSchedulerです。asyncSchedulerは、上記のようにsetInterval機能する作業をスケジュールsetTimeoutし、別のメッセージをキューにプッシュします。

2つのソリューションをwhileループで試してみましたが、最初の1つは完全にブラウザをフリーズさせましたが、2番目のソリューションは非常に遅れましたが、whileループ内のコンソールに何かを出力できました。なぜ2番目のほうがパフォーマンスが少し優れているのか、実際にはわかりませんが、どちらも実際に必要なものではありません。あなたはすでに良い解決策を思いついたので、この回答が最初の解決策がそれほどうまく機能しない理由を理解するのに役立つことを願っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.