ฉันจะทำให้ setInterval ทำงานได้อย่างไรเมื่อแท็บไม่ทำงานใน Chrome


190

ฉันมี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เรียกใช้ฟังก์ชันในแต่ละวินาทีซึ่งจะไม่เท่ากับ 30 แต่จะมีเพียง 1 หรือ 2 หากแท็บไม่ทำงาน

ฉันเดาว่าสิ่งนี้ทำโดยการออกแบบเพื่อปรับปรุงประสิทธิภาพ แต่มีวิธีใดที่จะปิดการทำงานนี้หรือไม่ จริง ๆ แล้วมันเป็นข้อเสียในสถานการณ์ของฉัน


3
อาจไม่เว้นแต่คุณแฮ็คมันพร้อมกับDateวัตถุเพื่อดูว่าเวลาผ่านไปแล้วจริงๆ
alex

คุณสามารถอธิบายเพิ่มเติมเกี่ยวกับสถานการณ์ของคุณได้ไหม? บางทีมันอาจจะไม่ใช่ข้อเสีย
James

2
คุณหมายถึงการเปลี่ยนแปลงรหัสนี้และสิ่งที่คุณถามมีการกล่าวถึงที่นี่ด้วย - Oliver Mattos โพสต์การแก้ไขบางอย่างบางทีมันก็ใช้ได้ในกรณีของคุณเช่นกัน?
Shadow Wizard เป็นหูสำหรับคุณ

6
Dateมันเกือบจะตลอดเวลาที่ดีที่สุดเพื่อภาพเคลื่อนไหวที่สำคัญเกี่ยวกับปริมาณของเวลาจริงผ่านไปนับตั้งแต่จุดเริ่มต้นของการเคลื่อนไหวในขณะที่อ่านจาก เพื่อที่ว่าเมื่อช่วงเวลาไม่ได้ดำเนินการอย่างรวดเร็ว (ด้วยเหตุผลนี้หรือเหตุผลอื่น ๆ ) แอนิเมชันเพิ่งจะกระตุกขึ้นไม่ช้าลง
bobince

1
ชื่อของคำถามทำให้ฉันอยู่ที่นี่ แต่กรณีการใช้งานของฉันแตกต่างกันเล็กน้อย - ฉันต้องการโทเค็นการรับรองความถูกต้องรีเฟรชโดยไม่คำนึงถึงการไม่ใช้งานของแท็บ ถ้านั่นเกี่ยวข้องกับคุณลองดูคำตอบของฉันที่นี่
Erez Cohen

คำตอบ:


153

ในแท็บที่ไม่ใช้งานของเบราว์เซอร์ส่วนใหญ่มีการดำเนินการที่มีลำดับความสำคัญต่ำซึ่งอาจส่งผลต่อตัวนับ JavaScript

หากค่าของการเปลี่ยนแปลงของคุณจะถูกคำนวณโดยใช้เวลาจริงผ่านไประหว่างเฟรมเพิ่มขึ้นคงที่แทนในแต่ละช่วงคุณไม่เพียง แต่แก้ปัญหานี้ แต่ยังสามารถบรรลุการเคลื่อนไหวปกคลุมโดยใช้requestAnimationFrameเท่าที่จะสามารถรับได้ถึง 60fps ถ้าประมวลผลไม่ได้ ยุ่งมาก

นี่คือตัวอย่างของวานิลลาจาวาสคริปต์ในการเปลี่ยนคุณสมบัติของภาพเคลื่อนไหวโดยใช้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 vs JS "แอนิเมชั่น"

ปัญหานี้และอื่น ๆ อีกมากมายสามารถหลีกเลี่ยงได้โดยใช้การเปลี่ยน CSS / ภาพเคลื่อนไหว CSS แทนภาพเคลื่อนไหวที่ใช้ JavaScript ซึ่งเพิ่มค่าใช้จ่ายจำนวนมาก ฉันขอแนะนำปลั๊กอิน jQueryนี้ที่ให้คุณได้รับประโยชน์จากการเปลี่ยน CSS เช่นเดียวกับanimate()วิธีการต่างๆ


1
ฉันลองสิ่งนี้ใน FireFox 5 และ 'setInterva'l ยังคงทำงานแม้ว่าแท็บจะไม่โฟกัส รหัสของฉันใน 'setInterval' จะเลื่อนสไลด์โชว์โดยใช้ 'animate ()' ดูเหมือนว่าภาพเคลื่อนไหวจะถูกจัดลำดับโดย FireFox เมื่อฉันกลับไปที่แท็บ FireFox จะปรากฏคิวทันทีหลังจากที่อื่นทำให้เกิดสไลด์โชว์ที่เคลื่อนไหวอย่างรวดเร็วจนกระทั่งคิวนั้นว่างเปล่า
nthpixel

@nppixel จะเพิ่ม. stop (ตามคำตอบของ www) ช่วยในสถานการณ์ททท (แต่ละครั้งมันจะเป็นการล้างภาพเคลื่อนไหวก่อนหน้านี้)

@gordatron -. stop ไม่ช่วยสถานการณ์ของฉัน พฤติกรรมเดียวกัน และตอนนี้ฉันใช้ FireFox 6.0.2 แล้ว ฉันสงสัยว่าเป็นวิธีที่ jQuery ใช้. เคลื่อนไหวหรือไม่
nthpixel

@cvsguimaraes - ใช่จุดดี คุณรู้อะไรในข้อมูลจำเพาะที่รับประกันว่าคนทำงานเว็บจะทำงานแม้ในแท็บพื้นหลังหรือไม่? ฉันเป็นห่วงน้อยที่ผู้ค้าเบราว์เซอร์จะตัดสินใจโดยพลการในอนาคตเช่นกัน ...
UpTheCreek

ฉันจะเปลี่ยนบรรทัดถัดไปสุดท้ายของรหัสในการอ่านbefore = now;เพื่อให้ได้เวลาที่ผ่านมาตั้งแต่เริ่มต้นแทนการสิ้นสุดของสายก่อน นี่คือสิ่งที่คุณต้องการเมื่อเคลื่อนไหว ตามที่เป็นอยู่ในขณะนี้หากการดำเนินการของฟังก์ชั่นช่วงเวลาใช้เวลา 15ms elapsedTimeจะให้ 35ms (แทน 50ms ซึ่งเป็นช่วงเวลา) ครั้งต่อไปที่มันถูกเรียก (เมื่อแท็บใช้งานอยู่)
Jonas Berlin

71

ฉันพบปัญหาเดียวกันกับเครื่องเล่นเพลงและไฟล์ 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);

Javascript หลัก:

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;
    }
});

6
เรียบร้อย! ตอนนี้หวังว่าพวกเขาจะไม่ "แก้ไข" สิ่งนี้
pimvdb

2
ที่ดี! ควรใช้วิธีการนี้เมื่อคุณต้องการให้ตัวจับเวลาทำงาน แต่ไม่ใช่เพื่อแก้ไขปัญหาแอนิเมชั่นบางอย่าง!
Konstantin Smolyanin

1
ฉันทำเครื่องเมตรอนอมที่ยอดเยี่ยมด้วยสิ่งนี้ น่าสนใจว่าเครื่องตีกลอง html5 ยอดนิยมทั้งหมดไม่ใช้วิธีนี้และใช้ setTimeout ปกติที่ด้อยกว่าแทน skyl.github.io/grimoire/fretboard-prototype.html - chrome หรือ Safari เล่นได้ดีที่สุดในตอนนี้
Skylar Saveland

พวกเขาจะ "แก้ไข" หากนักพัฒนาเริ่มใช้งานในทางที่ผิด ด้วยข้อยกเว้นที่หายากแอปของคุณไม่สำคัญอย่างยิ่งที่จะต้องใช้ทรัพยากรในพื้นหลังเพื่อให้ประสบการณ์การใช้งานของผู้ใช้ดีขึ้น
Gunchars

41

มีวิธีแก้ปัญหาในการใช้ Web Workers (ดังที่กล่าวไว้ก่อนหน้า) เนื่องจากพวกเขาทำงานในกระบวนการแยกต่างหากและไม่ได้ชะลอตัวลง

ฉันได้เขียนสคริปต์เล็ก ๆ ที่สามารถใช้งานได้โดยไม่มีการเปลี่ยนแปลงโค้ดของคุณ - มันแทนที่ฟังก์ชั่น setTimeout, clearTimeout, setInterval, clearInterval

เพียงรวมไว้ก่อนรหัสของคุณทั้งหมด

ข้อมูลเพิ่มเติมที่นี่


1
ฉันได้ทดสอบในโครงการรวมถึงห้องสมุดที่ใช้ตัวจับเวลา (ดังนั้นฉันจึงไม่สามารถใช้งานตัวเองได้) มันทำงานเหมือนจับใจ ขอบคุณสำหรับห้องสมุดนี้
ArnaudR

@ ruslan-tushov เพิ่งลองใช้กับ chrome 60 แต่ดูเหมือนว่าจะไม่มีผลเลย ... ฉันกำลังเรียกใช้ฟังก์ชั่นบางตัวจาก setTimeout หลายตัวเพื่อเพิ่ม / ลบองค์ประกอบใน DOM ที่เคลื่อนไหวด้วย css ภาพเคลื่อนไหวและฉันเห็นพวกมันค้าง ด้วยความล่าช้าหลังจากสวิตช์แท็บ (เหมือนปกติโดยไม่ต้องมีปลั๊กอิน)
neoDev

@neoDev คุณโหลด HackTimer.js (หรือ HackTimer.min.js) หน้า JavaScript อื่น ๆ หรือไม่?
Davide Patti

@neoDev มันฟังดูแปลกจริง ๆ เพราะฉันเพิ่งลองมาแล้วมันใช้งานได้ดี
Davide Patti

@DurdenP ใช่ฉันพยายามที่จะวางไว้ก่อน JavaScript อื่น ๆ อาจเป็นเพราะฉันใช้ภาพเคลื่อนไหว css หรือ ฉันจำได้ว่าฉันลองเว็บเวิร์ค แต่ไม่มีโชค
neoDev

13

แค่ทำสิ่งนี้:

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()วิธีการในขณะนี้ที่หนีบจะส่งไม่เกินหนึ่งหมดเวลาต่อวินาทีในแท็บไม่ได้ใช้งาน นอกจากนี้ตอนนี้จะจับการหมดเวลาซ้อนเป็นค่าที่น้อยที่สุดที่อนุญาตโดยข้อกำหนดของ HTML5: 4 ms (แทนที่จะเป็น 10 ms ที่ใช้ในการหนีบ)


1
สิ่งนี้เป็นเรื่องดีที่จะรู้ - ตัวอย่างเช่นการอัปเดต Ajax ที่ข้อมูลล่าสุดถูกต้องเสมอ - แต่สำหรับคำถามที่โพสต์ไม่ได้หมายความว่าภาพเคลื่อนไหวช้าลงอย่างมาก / หยุดชั่วคราวเนื่องจาก "a" จะไม่เพิ่มจำนวนครั้งที่เหมาะสม ?

5

ฉันคิดว่าความเข้าใจที่ดีที่สุดเกี่ยวกับปัญหานี้อยู่ในตัวอย่างนี้: http://jsfiddle.net/TAHDb/

ฉันกำลังทำสิ่งง่าย ๆ ที่นี่:

มีช่วงเวลา 1 วินาทีและแต่ละครั้งซ่อนช่วงแรกและย้ายไปยังช่วงเวลาสุดท้ายและแสดงช่วงที่ 2

ถ้าคุณอยู่ในหน้ามันทำงานตามที่ควรจะเป็น แต่ถ้าคุณซ่อนแท็บไว้สักครู่เมื่อคุณกลับมาคุณจะเห็นสิ่งแปลก ๆ

มันเหมือนกับกิจกรรมทั้งหมดที่ไม่ได้เกิดขึ้นในช่วงเวลาที่คุณไม่ได้ใช้งานในขณะนี้จะเกิดขึ้นทั้งหมดใน 1 ครั้ง ดังนั้นสักสองสามวินาทีคุณจะได้รับเหตุการณ์ X พวกมันเร็วมากจนเป็นไปได้ที่จะเห็นทั้ง 6 ช่วงพร้อมกัน

ดังนั้นมันจึงเป็นโครเมี่ยมที่ทำให้เกิดความล่าช้าเท่านั้นดังนั้นเมื่อคุณกลับมาเหตุการณ์ทั้งหมดจะเกิดขึ้น แต่ทั้งหมดในครั้งเดียว ...

แอปพลิเคชั่น pratical นี้เกิดขึ้นสำหรับสไลด์โชว์อย่างง่าย ลองนึกภาพตัวเลขที่เป็นรูปภาพและหากผู้ใช้อยู่กับแท็บที่ซ่อนเมื่อเขากลับมาเขาจะเห็น img ทั้งหมดลอยตัวอยู่ทั้งหมด

เพื่อแก้ไขปัญหานี้ใช้หยุด (จริงจริง) เช่น pimvdb บอก นี่จะล้างคิวเหตุการณ์


4
ในความเป็นจริงนี้เป็นเพราะrequestAnimationFramejQuery ที่ใช้ เนื่องจากมีนิสัยแปลก ๆ (เช่นนี้) พวกเขาจึงลบออก ใน 1.7 คุณไม่เห็นพฤติกรรมนี้ jsfiddle.net/TAHDb/1 เนื่องจากช่วงเวลาหนึ่งครั้งต่อวินาทีสิ่งนี้ไม่ส่งผลกระทบต่อปัญหาที่ฉันโพสต์เนื่องจากค่าสูงสุดสำหรับแท็บที่ไม่ได้ใช้งานก็คือหนึ่งครั้งต่อวินาทีดังนั้นมันจึงไม่ต่างกัน
pimvdb

4

สำหรับฉันมันไม่สำคัญที่จะเล่นเสียงในพื้นหลังเหมือนกับคนอื่น ๆ ที่นี่ปัญหาของฉันคือการที่ฉันมีภาพเคลื่อนไหวบางส่วนและพวกเขาทำตัวเหมือนบ้าเมื่อคุณอยู่ในแท็บอื่น ๆ และกลับมาที่พวกเขา โซลูชั่นของฉันถูกวางภาพเคลื่อนไหวเหล่านี้ภายในถ้านั่นคือการป้องกันไม่ให้แท็บใช้งาน :

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

ขอบคุณที่ภาพเคลื่อนไหวของฉันทำงานเฉพาะเมื่อมีการใช้งานแท็บ ฉันหวังว่านี่จะช่วยให้ใครบางคนกับกรณีของฉัน


1
ฉันใช้สิ่งนี้setInterval(() => !document.hidden && myfunc(), 1000)และทำงานได้อย่างสมบูรณ์
Didi Bear

4

ทั้งสองsetIntervalและrequestAnimationFrameไม่ทำงานเมื่อแท็บไม่ทำงานหรือทำงาน แต่ไม่ใช่ในช่วงเวลาที่เหมาะสม ทางออกคือการใช้แหล่งอื่นสำหรับเหตุการณ์เวลา ตัวอย่างเช่นเว็บซ็อกเก็ตหรือผู้ปฏิบัติงานเว็บเป็นแหล่งเหตุการณ์สองแหล่งที่ทำงานได้ดีในขณะที่แท็บไม่ทำงาน ดังนั้นไม่จำเป็นต้องย้ายรหัสทั้งหมดของคุณไปยังผู้ปฏิบัติงานเว็บเพียงใช้ผู้ปฏิบัติงานเป็นแหล่งเวลาเหตุการณ์:

// 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ของตัวอย่างนี้


"เพียงแค่ใช้คนงานเป็นแหล่งเหตุการณ์เวลา" ขอบคุณสำหรับความคิด
Promod Sampath Elvitigala

1

อิทธิพลจากห้องสมุด Ruslan Tushov ของเราได้สร้างเล็ก ๆ ของตัวเองห้องสมุด เพียงแค่เพิ่มสคริปต์ใน<head>และมันจะแก้ไขsetIntervalและกับคนที่ใช้setTimeoutWebWorker


เพิ่งลองใช้กับ chrome 60 แต่ดูเหมือนว่าจะไม่มีผลเลย ... ฉันกำลังเรียกใช้ฟังก์ชั่นบางตัวจาก setTimeout หลายตัวเพื่อเพิ่ม / ลบองค์ประกอบไปยัง DOM ที่เคลื่อนไหวโดยใช้ภาพเคลื่อนไหว css และฉันเห็นพวกมันค้างด้วยความล่าช้าเล็กน้อย เปลี่ยนแท็บ (เหมือนปกติโดยไม่ต้องใช้ปลั๊กอิน)
neoDev

ฉันใช้กับ Chrome 60 คุณสามารถสาธิตและโพสต์ลงบนปัญหา GitHub ได้หรือไม่?
Mariy

1

การเล่นไฟล์เสียงทำให้การใช้งาน Javascript เต็มรูปแบบเป็นพื้นหลัง

สำหรับฉันมันเป็นทางออกที่ง่ายและรบกวนน้อยที่สุด - นอกเหนือจากการเล่นเสียงจาง ๆ / เกือบว่างเปล่าไม่มีผลข้างเคียงอื่น ๆ ที่อาจเกิดขึ้น

คุณสามารถดูรายละเอียดได้ที่นี่: https://stackoverflow.com/a/51191818/914546

(จากคำตอบอื่น ๆ ฉันเห็นว่าบางคนใช้คุณสมบัติต่าง ๆ ของแท็กเสียงฉันสงสัยว่าเป็นไปได้หรือไม่ที่จะใช้แท็กเสียงเพื่อประสิทธิภาพเต็มรูปแบบโดยไม่ต้องเล่นอะไรจริง ๆ )


0

หมายเหตุ:วิธีนี้ไม่เหมาะถ้าคุณชอบช่วงเวลาของคุณทำงานบนพื้นหลังเช่นเล่นเสียงหรือ ... แต่ถ้าคุณสับสนเช่นเกี่ยวกับภาพเคลื่อนไหวของคุณทำงานไม่ถูกต้องเมื่อกลับมาที่หน้า (แท็บ) นี่คือ ทางออกที่ดี

มีหลายวิธีในการบรรลุเป้าหมายนี้อาจ "WebWorkers" เป็นมาตรฐานที่สุดแต่แน่นอนว่าไม่ใช่วิธีที่ง่ายและสะดวกโดยเฉพาะถ้าคุณไม่มีเวลาเพียงพอดังนั้นคุณสามารถลองด้วยวิธีนี้:

►แนวคิดพื้นฐาน:

1- สร้างชื่อสำหรับช่วงเวลาของคุณ (หรือภาพเคลื่อนไหว) และตั้งช่วงเวลาของคุณ (ภาพเคลื่อนไหว) ดังนั้นมันจะทำงานเมื่อผู้ใช้เปิดหน้าเว็บครั้งแรก: var interval_id = setInterval(your_func, 3000);

2- โดย$(window).focus(function() {});และ$(window).blur(function() {});คุณสามารถปิดการใช้งานclearInterval(interval_id)เบราว์เซอร์ทุกครั้ง (แท็บ) และเรียกใช้ช่วงเวลาใหม่ของคุณ (ภาพเคลื่อนไหว) เบราว์เซอร์ทุกครั้ง (แท็บ) จะได้รับอีกครั้งโดยinterval_id = setInterval();

รหัส►SAMPLE:

var interval_id = setInterval(your_func, 3000);

$(window).focus(function() {
    interval_id = setInterval(your_func, 3000);
});
$(window).blur(function() {
    clearInterval(interval_id);
    interval_id = 0;
});

0

เป็นคำถามที่ค่อนข้างเก่า แต่ฉันพบปัญหาเดียวกัน
ถ้าคุณเรียกใช้เว็บของคุณในโครเมี่ยมที่คุณสามารถอ่านผ่านทางนี้โพสต์แท็บพื้นหลังใน Chrome 57

โดยทั่วไปตัวจับเวลาช่วงอาจทำงานได้หากไม่ได้ใช้งบประมาณตัวจับเวลาหมด
การใช้งบประมาณจะขึ้นอยู่กับการใช้เวลา CPU ของงานภายในตัวจับเวลา
จากภาพจำลองของฉันฉันวาดวิดีโอลงบนผืนผ้าใบและส่งไปที่ WebRTC
การเชื่อมต่อวิดีโอ webrtc จะทำให้การปรับปรุงแม้แท็บไม่ทำงาน

แต่คุณต้องใช้แทนsetInterval ไม่แนะนำสำหรับการแสดงผล UI requestAnimationFrame

มันจะเป็นการดีกว่าถ้าได้ฟังvisibilityChangeเหตุการณ์และเปลี่ยนการแสดงความคิดในทางที่ผิด

นอกจากนี้คุณสามารถลอง @ kaan-soral และควรทำงานตามเอกสาร


-1

นี่คือทางออกคร่าวๆของฉัน

(function(){
var index = 1;
var intervals = {},
    timeouts = {};

function postMessageHandler(e) {
    window.postMessage('', "*");

    var now = new Date().getTime();

    sysFunc._each.call(timeouts, function(ind, obj) {
        var targetTime = obj[1];

        if (now >= targetTime) {
            obj[0]();
            delete timeouts[ind];
        }
    });
    sysFunc._each.call(intervals, function(ind, obj) {
        var startTime = obj[1];
        var func = obj[0];
        var ms = obj[2];

        if (now >= startTime + ms) {
            func();
            obj[1] = new Date().getTime();
        }
    });
}
window.addEventListener("message", postMessageHandler, true);
window.postMessage('', "*");

function _setTimeout(func, ms) {
    timeouts[index] = [func, new Date().getTime() + ms];
    return index++;
}

function _setInterval(func, ms) {
    intervals[index] = [func, new Date().getTime(), ms];
    return index++;
}

function _clearInterval(ind) {
    if (intervals[ind]) {
        delete intervals[ind]
    }
}
function _clearTimeout(ind) {
    if (timeouts[ind]) {
        delete timeouts[ind]
    }
}

var intervalIndex = _setInterval(function() {
    console.log('every 100ms');
}, 100);
_setTimeout(function() {
    console.log('run after 200ms');
}, 200);
_setTimeout(function() {
    console.log('closing the one that\'s 100ms');
    _clearInterval(intervalIndex)
}, 2000);

window._setTimeout = _setTimeout;
window._setInterval = _setInterval;
window._clearTimeout = _clearTimeout;
window._clearInterval = _clearInterval;
})();

การpostMessageHandlerเรียกใช้เหตุการณ์ของมันเองซึ่งกำลังจัดการอยู่ดังนั้นจึงมีการวนซ้ำไม่สิ้นสุดที่ไม่ได้บล็อก UI และในขณะที่มันวนลูปไม่สิ้นสุดการตรวจสอบกับการจัดการเหตุการณ์แต่ละครั้งหากมีการหมดเวลาหรือฟังก์ชั่นช่วงเวลาที่จะเรียกใช้
foobored

-1

ฉันสามารถเรียกฟังก์ชันการเรียกกลับของฉันอย่างน้อย 250ms โดยใช้แท็กเสียงและจัดการกับเหตุการณ์ที่เกิดขึ้นเมื่อเวลาผ่านไป มันเรียกว่า 3-4 ครั้งในหนึ่งวินาที มันดีกว่าหนึ่งวินาที lagging setTimeout

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.