Chrome에서 탭이 비활성 상태 일 때 setInterval도 작동하게하려면 어떻게해야하나요? 테스트 사례를 만들었습니다 ( http://jsfiddle.net/7f6DX/3/ ). var

나는 한 setInterval코드의 조각 30 회 두 번째를 실행. 이것은 잘 작동하지만 다른 탭을 선택하면 (코드가있는 탭이 비활성화되도록) setInterval어떤 이유로 유휴 상태로 설정됩니다.

이 간단한 테스트 사례를 만들었습니다 ( http://jsfiddle.net/7f6DX/3/ ).

var $div = $('div');
var a = 0;

setInterval(function() {
    a++;
    $div.css("left", a)
}, 1000 / 30);

이 코드를 실행 한 다음 다른 탭으로 전환하고 몇 초 기다렸다가 다시 돌아 가면 다른 탭으로 전환했을 때의 시점까지 애니메이션이 계속됩니다. 따라서 탭이 비활성 상태 인 경우 애니메이션이 초당 30 회 실행되지 않습니다. 이것은 setInterval함수가 1 초마다 호출 되는 횟수를 세어 확인할 수 있습니다 . 탭이 비활성화되어 있으면 30이 아니라 1 또는 2입니다.

나는 이것이 성능을 향상시키기 위해 의도적으로 설계된 것이라고 생각하지만이 동작을 비활성화하는 방법이 있습니까? 내 시나리오에서는 실제로 단점입니다.



답변

대부분의 브라우저에서 비활성 탭은 우선 순위가 낮으므로 JavaScript 타이머에 영향을 줄 수 있습니다.

각 간격마다 고정 증분 대신 프레임간에 실시간 경과 시간을 사용하여 전환 값을 계산 경우이 문제를 해결할 수있을뿐만 아니라 프로세서가없는 경우 최대 60fps를 얻을 수 있으므로 requestAnimationFrame 을 사용하여 smother 애니메이션을 얻을 수도 있습니다. 아주 바쁜.

다음은 다음을 사용하는 애니메이션 속성 전환의 바닐라 JavaScript 예제입니다 requestAnimationFrame.

var target = document.querySelector('div#target')
var startedAt, duration = 3000
var domain = [-100, window.innerWidth]
var range = domain[1] - domain[0]

function start() {
  startedAt = Date.now()
  updateTarget(0)
  requestAnimationFrame(update)
}

function update() {
  let elapsedTime = Date.now() - startedAt

  // playback is a value between 0 and 1
  // being 0 the start of the animation and 1 its end
  let playback = elapsedTime / duration

  updateTarget(playback)

  if (playback > 0 && playback < 1) {
  	// Queue the next frame
  	requestAnimationFrame(update)
  } else {
  	// Wait for a while and restart the animation
  	setTimeout(start, duration/10)
  }
}

function updateTarget(playback) {
  // Uncomment the line below to reverse the animation
  // playback = 1 - playback

  // Update the target properties based on the playback position
  let position = domain[0] + (playback * range)
  target.style.left = position + 'px'
  target.style.top = position + 'px'
  target.style.transform = 'scale(' + playback * 3 + ')'
}

start()
body {
  overflow: hidden;
}

div {
    position: absolute;
    white-space: nowrap;
}
<div id="target">...HERE WE GO</div>


백그라운드 작업의 경우 (비 UI 관련)

@UpTheCreek 의견 :

프레젠테이션 문제에는 적합하지만 계속 실행해야 할 사항이 있습니다.

당신이 있음을 백그라운드 작업이있는 경우 요구 사항이 정확하게 주어진 간격으로 실행되는, 당신이 사용할 수있는 HTML5 웹 노동자 . 한 번 봐 가지고 아래 Möhre의 대답 자세한 내용을 …

CSS 대 JS “애니메이션”

상당한 오버 헤드를 추가하는 JavaScript 기반 애니메이션 대신 CSS 전환 / 애니메이션을 사용하면 이 문제와 다른 많은 문제를 피할 수 있습니다. 메소드 와 마찬가지로 CSS 전환을 활용할 수있는 이 jQuery 플러그인 을 권장 animate()합니다.


답변

오디오 페이딩 및 HTML5 플레이어와 동일한 문제가 발생했습니다. 탭이 비활성화되면 멈추었습니다. 그래서 WebWorker가 간격 / 시간 초과를 제한없이 사용할 수 있음을 알았습니다. “틱”을 기본 자바 스크립트에 게시하는 데 사용합니다.

WebWorkers 코드 :

var fading = false;
var interval;
self.addEventListener('message', function(e){
    switch (e.data) {
        case 'start':
            if (!fading){
                fading = true;
                interval = setInterval(function(){
                    self.postMessage('tick');
                }, 50);
            }
            break;
        case 'stop':
            clearInterval(interval);
            fading = false;
            break;
    };
}, false);

주요 자바 스크립트 :

var player = new Audio();
player.fader = new Worker('js/fader.js');
player.faderPosition = 0.0;
player.faderTargetVolume = 1.0;
player.faderCallback = function(){};
player.fadeTo = function(volume, func){
    console.log('fadeTo called');
    if (func) this.faderCallback = func;
    this.faderTargetVolume = volume;
    this.fader.postMessage('start');
}
player.fader.addEventListener('message', function(e){
    console.log('fader tick');
    if (player.faderTargetVolume > player.volume){
        player.faderPosition -= 0.02;
    } else {
        player.faderPosition += 0.02;
    }
    var newVolume = Math.pow(player.faderPosition - 1, 2);
    if (newVolume > 0.999){
        player.volume = newVolume = 1.0;
        player.fader.postMessage('stop');
        player.faderCallback();
    } else if (newVolume < 0.001) {
        player.volume = newVolume = 0.0;
        player.fader.postMessage('stop');
        player.faderCallback();
    } else {
        player.volume = newVolume;
    }
});


답변

웹 작업자는 별도의 프로세스에서 실행되며 속도가 느려지지 않기 때문에 (앞서 언급했듯이) 사용하는 솔루션이 있습니다.

코드를 변경하지 않고 사용할 수있는 작은 스크립트를 작성했습니다. setTimeout, clearTimeout, setInterval, clearInterval 함수를 무시합니다.

모든 코드 앞에 포함하십시오.

더 많은 정보는 여기에


답변

그냥 이렇게 :

var $div = $('div');
var a = 0;

setInterval(function() {
    a++;
    $div.stop(true,true).css("left", a);
}, 1000 / 30);

비활성 브라우저 탭은 일부 setInterval또는 setTimeout기능을 버퍼링 합니다.

stop(true,true) 버퍼링 된 모든 이벤트를 중지하고 마지막 애니메이션 만 즉시 실행합니다.

window.setTimeout()방법은 비활성 탭에서 초당 최대 1 개의 타임 아웃을 보내도록 고정됩니다. 또한 이제 중첩 시간 초과를 HTML5 사양에서 허용하는 가장 작은 값인 4ms (클램핑하는 데 사용 된 10ms 대신)로 고정합니다.


답변

이 문제에 대한 최선의 이해는이 예제에 있다고 생각합니다. http://jsfiddle.net/TAHDb/

나는 여기서 간단한 일을하고있다 :

1 초 간격을두고 매번 첫 번째 스팬을 숨기고 마지막으로 이동하여 두 번째 스팬을 표시하십시오.

페이지에 머무르면 예상대로 작동합니다. 그러나 몇 초 동안 탭을 숨기면 돌아올 때 위조 된 것이 나타납니다.

비활성화 된 시간 동안 발생하지 않은 모든 이벤트는 이제 한 번만 발생합니다. 몇 초 동안 X 이벤트처럼 보일 것입니다. 6 개 범위를 한 번에 모두 볼 수있을 정도로 빠릅니다.

그래서 이음새 크롬은 이벤트 만 지연하므로 모든 이벤트가 다시 발생하면 한 번에 모두 발생합니다 …

실용적인 응용 프로그램은 간단한 슬라이드 쇼를위한이 문제였습니다. 숫자가 이미지라고 상상해보십시오. 사용자가 돌아 왔을 때 탭이 숨겨져 있으면 모든 imgs가 떠 다니는 것을 볼 수 있습니다.

이 문제를 해결하려면 pimvdb와 같은 stop (true, true)을 사용하십시오. 이벤트 큐를 지 웁니다.


답변

나에게 여기서 다른 사람들처럼 백그라운드에서 오디오를 재생하는 것은 중요하지 않습니다. 내 문제는 애니메이션이 있고 다른 탭에 있고 다시 돌아올 때 미친 듯이 행동했다는 것입니다. 내 탭에서 비활성 탭을 막는 경우 내 솔루션이 이러한 애니메이션을 넣었습니다 .

if (!document.hidden){ //your animation code here }

덕분에 탭이 활성화 된 경우 에만 애니메이션이 실행 되었습니다. 이것이 내 사건에 도움이되기를 바랍니다.


답변

모두 setIntervalrequestAnimationFrame탭이 비활성 또는 작업하지만,하지 않을 권리 기간에하지 않을 때 일을. 해결책은 시간 이벤트에 다른 소스를 사용하는 것입니다. 예를 들어, 웹 소켓 또는 웹 워커 는 탭이 비활성 상태 일 때 제대로 작동하는 두 가지 이벤트 소스입니다. 따라서 모든 코드를 웹 워커로 옮길 필요가 없습니다. 워커를 시간 이벤트 소스로 사용하십시오.

// worker.js
setInterval(function() {
    postMessage('');
}, 1000 / 50);

.

var worker = new Worker('worker.js');
var t1 = 0;
worker.onmessage = function() {
    var t2 = new Date().getTime();
    console.log('fps =', 1000 / (t2 - t1) | 0);
    t1 = t2;
}

이 샘플의 jsfiddle 링크 .