タブまたはウィンドウがアクティブでない場合、ブラウザはどのようにJavaScriptを一時停止/変更しますか?


168

背景:ユーザーが注意を払っているかどうかを検出する必要があるユーザーインターフェイステストをいくつか行っています。しかし、この質問はありませんについてのページの可視性のAPI

具体的には、現在のタブがアクティブではない場合、または別のブラウザーでブラウザーウィンドウがアクティブでない場合に、JavaScriptコードがどのように影響を受けるかを知りたいです。これまでに次のことを調べました。

次の質問があります。

  • モバイルブラウザー以外に、デスクトップブラウザーはタブがアクティブでないときにJSの実行を一時停止しますか?いつ、どのブラウザ?
  • どのブラウザーがsetInterval繰り返しを減らしますか?限界まで減ったのか、それともパーセンテージだけ減ったのか?たとえば、10msの繰り返しと5000msの繰り返しがある場合、それぞれにどのような影響がありますか?
  • これらの変更は、タブだけではなく、ウィンドウがフォーカスされていない場合に発生しますか?(OS APIが必要なため、検出が難しくなると思います。)
  • アクティブなタブで観察されない他の影響はありますか?彼らはそうでなければ正しく実行されるであろうことを台無しにすることができますか(すなわち前述のジャスミンテスト)?

一時停止すると、Facebookなどのサイトはバックグラウンドタブでチャットメッセージを受信しなくなります。
ジョセフ

1
一時停止はありませんが、タブ/ウィンドウがぼやけている場合、1000ミリ秒未満のsetInterval/ setTimeout時間が1000ミリ秒に変更されることを覚えています
Ian

19
@ProfPickle Webmasters?本当に?これはJSプログラミングの質問です。
Andrew Mao

1
@lan setInterval/ setTimeout1000ms未満の時間は、タブ/ウィンドウがぼやけているときに1000msに変更されます。伝えようとした内容が明確でない
Amol M Kulkarni 2013

4
+1すばらしい質問です。タブがアクティブでない場合のクランプ動作は標準の一部ではないと私が信じているので、ブラウザの動作を並べて比較するとよいでしょう。
UpTheCreek 2013

回答:


190

テスト1

私はこの目的のために特別にテストを書きました:
フレームレート分布:setInterval vs requestAnimationFrame

注:このテストはCPUをかなり集中的に使用します。requestAnimationFrameIE 9およびOpera 12ではサポートされていません。

テストでは、setIntervalrequestAnimationFrameを別のブラウザーで実行するのにかかる実際の時間を記録し、結果を分布の形で提供します。のミリ秒数を変更して、setIntervalさまざまな設定でどのように実行されるかを確認できます。遅延に関してはsetTimeouta setIntervalと同様に機能します。requestAnimationFrameブラウザによって異なりますが、通常はデフォルトで60fpsです。別のタブに切り替えたとき、または非アクティブなウィンドウがあるときに何が起こるかを確認するには、ページを開き、別のタブに切り替えてしばらく待ちます。これらの機能にかかる実際の時間は、非アクティブなタブに記録され続けます。

テスト2

それをテストする別の方法は、と繰り返しタイムスタンプを記録することであるsetIntervalrequestAnimationFrameし、取り外したコンソールに表示します。タブまたはウィンドウを非アクティブにすると、更新頻度(または更新されているかどうか)を確認できます。

結果

Chrome
Chrome setIntervalは、タブが非アクティブの場合、最小間隔を約1000ミリ秒に制限します。間隔が1000ミリ秒を超える場合、指定した間隔で実行されます。ウィンドウがフォーカスされていなくても問題ありません。間隔は、別のタブに切り替えたときにのみ制限されます。requestAnimationFrameタブが非アクティブになると一時停止します。

// Provides control over the minimum timer interval for background tabs.
const double kBackgroundTabTimerInterval = 1.0;

https://codereview.chromium.org/6546021/patch/1001/2001

Firefox
Chromeと同様に、Firefox setIntervalは、タブではなく(ウィンドウではなく)非アクティブな場合、最小間隔を約1000msに制限します。ただし、requestAnimationFrameタブが非アクティブの場合、実行速度は指数的に遅くなり、各フレームは1秒、2秒、4秒、8秒というようになります。

// The default shortest interval/timeout we permit
#define DEFAULT_MIN_TIMEOUT_VALUE 4 // 4ms
#define DEFAULT_MIN_BACKGROUND_TIMEOUT_VALUE 1000 // 1000ms

https://hg.mozilla.org/releases/mozilla-release/file/0bf1cadfb004/dom/base/nsGlobalWindow.cpp#l296

Internet Explorer
IEはsetInterval、タブが非アクティブな場合の遅延を制限しませんがrequestAnimationFrame、非アクティブなタブで一時停止します。ウィンドウのフォーカスが合っているかどうかは関係ありません。

エッジ
エッジ14から始まりsetInterval、非アクティブなタブでは1000ミリ秒に制限されています。requestAnimationFrame非アクティブなタブでは常に一時停止されます。

Safari
Chromeと同様に、Safari setIntervalはタブが非アクティブのときに1000ミリ秒で上限を設定します。requestAnimationFrameも一時停止しています。

Opera
Webkitエンジンの採用以来、OperaはChromeと同じ動作を示します。setInterval1000msで上限が設定されrequestAnimationFrame、タブが非アクティブになると一時停止します。

概要

非アクティブなタブの繰り返し間隔:

           setInterval      requestAnimationFrame 
Chrome
9-影響を受けない、サポートされない
10影響を受けず、一時停止
11+> = 1000ms一時停止

Firefox
3-影響を受けない、サポートされない
4は影響を受けない1
5+> = 1000ms 2 n s(n =非アクティブからのフレーム数)

IE
9-影響を受けない、サポートされない
一時停止の影響を受けていない10以上


13-影響を受けず、一時停止
14+> = 1000ms一時停止

サファリ
5-影響なしサポートなし
6影響を受けず、一時停止
7以上> = 1000ミリ秒の一時停止

オペラ
12-影響を受けない、サポートされない
15以上> = 1000ミリ秒の一時停止

すばらしい答えです。setIntervaland 以外の機能について他に考えられる違いはありrequestAnimationFrameますか?
Andrew Mao

1
@AndrewMao私が知っていることではありません。私はJSがで再度有効にあれば確実に検出するために、ライブラリーに取り組んでいたとき、私はこの問題に出くわしたsetIntervalrequestAnimationFrame。私が知っている事はあることsetTimeoutも同様に振る舞うとsetInterval、彼らは両方のFirefoxとChromeで同じ最小の背景間隔、および他のブラウザでは明白な限界を持っていることに。
アントニー

2
FirefoxののsetIntervalの最小値は、明らかに、URLを開いて変更することができabout:config、ブラウザで、変化するdom.min_background_timeout_value1000以外の何かに値を
ジョナス・ベルリン

これを使用して、ブラウザーが最小化されているときに5秒ごとにページをリロードできますか?ここに私の質問があります。
shaijut

1
requestAnimationFrameユーザーがアプリケーションを切り替えるだけの場合(Alt + TabをChromeから外す)、Chromeは呼び出し速度を一時停止/低下させないことに注意してください。Chromeでタブがアクティブである限り、「フレームレート」はほぼ一定です。
Marc

11

私が観察し何:アクティブでないタブの上にクローム、すべてのあなたのsetTimeout(で同じである必要がありますsetInterval)未満待って1000ミリ秒がに丸められている1000ミリ秒。長いタイムアウトは変更されないと思います。

Chrome 11およびFirefox 5.0以降の動作のようです:https : //developer.mozilla.org/en-US/docs/DOM/window.setTimeout#Inactive_tabs

さらに、ウィンドウ全体が非アクティブの場合は、このように動作するとは思いません(ただし、調査は非常に簡単に思えます)。


1
jQueryのfocusblurイベントは、それはおそらく両方の方法を動作することができるように、両方のタブとウィンドウのスイッチを検出するように見えます。しかし、ウィンドウが実際に表示されているかどうかはどのように検出されるのでしょうか。
Andrew Mao

2
それは内部ブラウ​​ザー実装であるため、実際にはjQueryJavaScriptとは関係ありません。

これを2016年後半に確認できますか?
vsync

0

これらを補完する新しい答え:chrome 78.0.3904.108で、別のタブに移動して戻ってきたときに、すべてのタイムアウト(1000ミリ秒未満ではない)が予想よりも少し長くかかっていることに気付きました。私が見ている動作は、「非アクティブなタブのすべてのタイムアウトが、追加の量だけ、最大1000msまで遅延する可能性がある」としてより正確に説明されています。

let timeouts = [ 500, 1000, 2000, 3000, 10000 ];

let minExcess = document.getElementsByClassName('minExcess')[0];

timeouts.forEach(ms => {
  let elem = document.getElementsByClassName(`t${ms}`)[0];
  let cnt = 0;
  
  let lastMs = +new Date();
  let f = () => {
    let curMs = +new Date();
    let disp = document.createElement('p');
    let net = curMs - lastMs;
    lastMs = curMs;
        
    setTimeout(f, ms);
    if (minExcess.value && (net - ms) < parseInt(minExcess.value)) return;
    
    disp.innerText = `${net},`;
    elem.appendChild(disp);
    if (++cnt > 10) elem.firstElementChild.remove();
    
  };
  setTimeout(f, ms);
  
});
body { font-size: 80%; }
div {
  max-height: 80px;
  overflow-x: auto;
  background-color: rgba(0, 0, 0, 0.1);
  margin-bottom: 2px;
  white-space: nowrap;
}
p { margin: 0; }
div > p {
  margin: 0;
  display: inline-block;
  vertical-align: top;
  margin-right: 2px;
}
input { margin: 0 0 10px 0; }
.t500:before { display: block; content: '500ms'; font-weight: bold; }
.t1000:before { display: block; content: '1000ms'; font-weight: bold; }
.t2000:before { display: block; content: '2000ms'; font-weight: bold; }
.t3000:before { display: block; content: '3000ms'; font-weight: bold; }
.t10000:before { display: block; content: '10000ms'; font-weight: bold; }
<p>Ignore any values delayed by less than this amount:</p>
<input type="text" class="minExcess" value="200" pattern="^[0-9]*$"/>
<div class="timeout t500"></div>
<div class="timeout t1000"></div>
<div class="timeout t2000"></div>
<div class="timeout t3000"></div>
<div class="timeout t10000"></div>

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