탭이나 창이 활성화되지 않은 경우 브라우저가 자바 스크립트를 일시 중지 / 변경하는 방법은 무엇입니까?


168

배경 : 사람들이주의를 기울이고 있는지 여부를 감지해야하는 일부 사용자 인터페이스 테스트를 수행하고 있습니다. 그러나이 질문은 페이지 가시성 API 에 관한 것이 아닙니다 .

특히 다른 브라우저에서 현재 탭이 활성화되어 있지 않거나 브라우저 창이 활성화되어 있지 않은 경우 Javascript 코드가 어떻게 영향을 받는지 알고 싶습니다. 지금까지 다음을 파헤 쳤습니다.

다음과 같은 질문이 있습니다.

  • 모바일 브라우저 이외에 탭이 활성화되지 않은 경우 데스크탑 브라우저가 JS 실행을 일시 중지합니까? 언제 그리고 어떤 브라우저?
  • 어떤 브라우저가 setInterval반복을 줄 입니까? 그것은 단지 한도 또는 백분율로 축소 되었습니까? 예를 들어, 10ms 반복 대 5000ms 반복이 있다면 각각 어떻게 영향을 받습니까?
  • 탭이 아닌 에 초점이 맞지 않으면 이러한 변경이 발생 합니까? (OS API가 필요하기 때문에 감지하기가 더 어려울 것이라고 생각합니다.)
  • 활성 탭에서 볼 수없는 다른 효과가 있습니까? 그렇지 않으면 올바르게 실행될 수있는 것들을 엉망으로 만들 수 있습니까 (즉, 위에서 언급 한 Jasmine 테스트)?

일시 중지 된 경우 Facebook과 같은 사이트는 배경 탭에서 채팅 메시지를받지 않습니다.
Joseph

1
예, 일시 정지는 없지만 탭 / 창이 흐리게 표시 될 때 1000ms 미만 의 setInterval/ setTimeout시간이 1000ms로 변경 되었다는 것을 기억합니다.
Ian

19
@ProfPickle 웹 마스터? 정말? 이것은 JS 프로그래밍 질문입니다.
Andrew Mao

1
탭 / 창이 흐리게 표시되면 @ lan setInterval/ setTimeout1000ms 미만의 시간이 1000ms로 변경됩니다. 무엇을 전달하려고했는지 확실치 않음
Amol M Kulkarni

4
+1 좋은 질문입니다. 탭이 활성화되어 있지 않을 때 클램핑 동작이 표준의 일부가 아니라고 생각하기 때문에 브라우저 동작을 나란히 비교하는 것이 좋습니다.
UpTheCreek

답변:


190

하나를 테스트

이 목적을 위해 특별히 테스트를 작성했습니다 :
프레임 속도 분포 : setInterval vs requestAnimationFrame

참고 :이 테스트는 CPU를 많이 사용합니다. requestAnimationFrameIE 9 및 Opera 12에서는 지원되지 않습니다.

이 테스트는 a setIntervalrequestAnimationFrame다른 브라우저에서 실행 하는 데 걸리는 실제 시간을 기록하고 배포 형태로 결과를 제공합니다. setInterval다른 설정에서 어떻게 실행되는지 확인 하기 위해 밀리 초 수를 변경할 수 있습니다 . 지연과 관련하여 setTimeout유사하게 작동합니다 setInterval. requestAnimationFrame일반적으로 브라우저에 따라 기본값은 60fps입니다. 다른 탭으로 전환하거나 비활성 창이있을 때 발생하는 상황을 보려면 페이지를 열고 다른 탭으로 전환 한 후 잠시 기다리십시오. 이 기능에 걸리는 실제 시간은 비활성 탭에 계속 기록됩니다.

테스트 2

그것을 테스트하는 또 다른 방법은 반복적으로 타임 스탬프를 기록하는 것입니다 setIntervalrequestAnimationFrame와 분리 된 콘솔에서 봅니다. 탭이나 창을 비활성화 할 때 업데이트 빈도 또는 업데이트 빈도를 확인할 수 있습니다.

결과

Chrome
Chrome setInterval은 탭이 비활성 상태 일 때 최소 간격 을 약 1000ms로 제한합니다 . 간격이 1000ms보다 높으면 지정된 간격으로 실행됩니다. 창의 초점이 맞지 않으면 상관 없습니다. 간격은 다른 탭으로 전환 할 때만 제한됩니다. 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비활성 탭 에서는 일시 중지합니다. 창의 초점이 맞지 않는지 여부는 중요하지 않습니다.

Edge
14부터 Edge setInterval는 비활성 탭에서 1000ms로 제한됩니다. requestAnimationFrame비활성 탭에서는 항상 일시 중지됩니다.

Safari
Chrome과 마찬가지로 Safari setInterval는 탭이 비활성 상태 일 때 1000ms로 제한됩니다. requestAnimationFrame또한 일시 중지됩니다.

Opera
웹킷 엔진을 채택한 이후로 Opera는 Chrome과 동일한 동작을 나타냅니다. setInterval은 1000ms로 제한되며 requestAnimationFrame탭이 비활성화되면 일시 중지됩니다.

요약

비활성 탭의 반복 간격 :

           setInterval      requestAnimationFrame 
Chrome
9- 영향을받지 않음
일시 중지되지 않은 10 개
11+> = 1000ms 일시 중지

Firefox
3- 영향을받지 않음
4 영향을받지 않은 1s
5+> = 1000ms 2 n s (n = 비활성 이후 프레임 수)

IE
9- 영향을받지 않음
일시 중지되지 않은 10+

가장자리
13- 일시 중지되지 않은 영향
14+> = 1000ms 일시 중지

원정 여행
5- 영향을받지 않음
6 일시 중지되지 않은 영향
7+> = 1000ms 일시 중지

오페라
12- 영향을받지 않음
15+> = 1000ms 일시 중지

좋은 대답입니다. setInterval및 이외의 기능에 대해 알려진 다른 차이점은 requestAnimationFrame무엇입니까?
Andrew Mao

1
@AndrewMao 내가 아는 것은 아닙니다. JS가 setIntervaland로 다시 활성화되었는지 확실하게 감지하기 위해 라이브러리에서 작업 할 때이 문제가 발생했습니다 requestAnimationFrame. 내가 아는 것은 Firefox와 Chrome에서 최소 배경 간격이 같고 다른 브라우저에서는 명백한 제한이 없다는 점에서 setTimeout와 비슷하게 작동 setInterval한다는 것입니다.
Antony

2
Firefox setInterval 최소값 about:config은 브라우저 에서 url을 열고 dom.min_background_timeout_value값을 1000 이외 의 값으로 변경하여 분명히 변경 될 수 있습니다 .
Jonas Berlin

브라우저를 최소화 할 때 5 초마다 페이지를 다시로드하는 데 이것을 사용할 수 있습니까?, 여기 내 질문이 있습니다.
shaijut

1
크롬은 requestAnimationFrame사용자가 단순히 응용 프로그램을 전환하는 경우 호출 되는 속도를 일시 중지 / 감소시키지 않습니다 (Chrome에서 Alt + Tab). Chrome에서 탭이 활성화되어있는 한 "프레임 속도"는 다소 일정합니다.
Marc

11

내가 관찰 무엇 : 비활성 탭에서 크롬 , 모든 setTimeout(동일해야합니다 setInterval)보다 작 대기 1000MS가 반올림됩니다 1000MS . 더 긴 시간 초과가 수정되지 않았다고 생각합니다.

Chrome 11Firefox 5.0 이후 동작 인 것 같습니다 : https://developer.mozilla.org/en-US/docs/DOM/window.setTimeout#Inactive_tabs

또한 전체 창이 비활성 상태 일 때이 방식으로 작동하지 않는다고 생각합니다 (그러나 조사하기는 매우 쉬운 것 같습니다).


1
jQuery focusblur이벤트는 탭과 창 스위치를 모두 감지하는 것으로 보이므로 두 가지 방식으로 작동 할 수 있습니다. 그러나 창이 실제로 표시되는지 여부를 어떻게 감지하는지 궁금합니다.
Andrew Mao

2
실제로 내부 브라우저 구현이므로 jQuery 또는 Javascript 와 연결되지 않습니다 .

2016 년 말에이를 확인할 수 있습니까?
vsync

0

더 새로운 답이를 보완하기 : 크롬 78.0.3904.108에 나는주의 모든 이러한 시간 초과 (단지 1000MS 아래 것) 조금 더 내가 다른 탭으로 이동 한 다음 돌아올 때 예상보다 복용. 내가보고있는 동작은 "비활성 탭의 모든 시간 초과가 추가 량만큼 최대 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.