जब टैब या विंडो सक्रिय नहीं होती है तो ब्राउज़र जावास्क्रिप्ट को कैसे रोक / बदल देता है?


168

पृष्ठभूमि: मैं कुछ उपयोगकर्ता इंटरफ़ेस परीक्षण कर रहा हूं जो यह पता लगाने की आवश्यकता है कि लोग ध्यान दे रहे हैं या नहीं। लेकिन, इस सवाल यह है कि नहीं के बारे में पेज दृश्यता एपीआई

विशेष रूप से, मैं जानना चाहूंगा कि यदि वर्तमान टैब सक्रिय नहीं है, या विभिन्न ब्राउज़रों में ब्राउज़र विंडो सक्रिय नहीं है, तो मेरा जावास्क्रिप्ट कोड कैसे प्रभावित होगा। मैंने अब तक निम्नलिखित को खोदा है:

मेरे पास निम्नलिखित प्रश्न हैं:

  • मोबाइल ब्राउज़र के अलावा, क्या डेस्कटॉप ब्राउज़र कभी जेएस निष्पादन को रोकते हैं जब एक टैब सक्रिय नहीं होता है? कब और कौन से ब्राउज़र?
  • कौन से ब्राउज़र setIntervalरिपीट कम करते हैं ? क्या यह सिर्फ एक सीमा तक या प्रतिशत से कम है? उदाहरण के लिए, यदि मेरे पास एक 10ms दोहराने बनाम 5000ms दोहराने है, तो प्रत्येक कैसे प्रभावित होगा?
  • क्या ये परिवर्तन तब होते हैं जब विंडो केवल फोकस से बाहर होती है, जैसे कि टैब के विपरीत? (मुझे लगता है कि यह पता लगाने के लिए कठिन होगा, क्योंकि इसके लिए ओएस एपीआई की आवश्यकता है।)
  • क्या कोई अन्य प्रभाव है जो एक सक्रिय टैब में नहीं देखा जाएगा? क्या वे चीजों को गड़बड़ कर सकते हैं जो अन्यथा सही तरीके से निष्पादित करेंगे (यानी उपरोक्त जैस्मिन परीक्षण)?

यदि उन्हें रोक दिया जाता है, तो फेसबुक जैसी साइटों को पृष्ठभूमि टैब पर कोई चैट संदेश प्राप्त नहीं होगा।
जोसफ

1
हाँ, कोई रोक नहीं है, लेकिन मुझे याद है कि टैब / विंडो के धुंधला होने पर 1000ms से कम setInterval/ का setTimeoutसमय 1000ms में बदल जाता है
इयान

19
@ProfPickle वेबमास्टर्स? वास्तव में? यह एक JS प्रोग्रामिंग प्रश्न है।
एंड्रयू माओ

1
जब टैब / विंडो धुंधली हो जाती है तो @lan setInterval/ 1000 से setTimeoutकम बार 1000ms में बदल जाते हैं। स्पष्ट नहीं है कि आपने क्या
संदेश

4
+1 महान प्रश्न। ब्राउज़र व्यवहार की तुलना में एक तरफ देखना अच्छा होगा, क्योंकि मेरा मानना ​​है कि जब टैब सक्रिय नहीं होता है तो क्लैम्पिंग व्यवहार किसी भी मानक का हिस्सा नहीं होता है।
UpTheCreek

जवाबों:


190

टेस्ट एक

मैंने इस उद्देश्य के लिए विशेष रूप से एक परीक्षण लिखा है:
फ़्रेम दर वितरण: सेटइंटरवल बनाम अनुरोधअनामकरणफ्रेम

नोट: यह परीक्षण काफी सीपीयू गहन है। requestAnimationFrameIE 9- और ओपेरा 12- द्वारा समर्थित नहीं है।

परीक्षण विभिन्न ब्राउज़रों में चलने setIntervalऔर requestAnimationFrameचलाने के लिए वास्तविक समय में लॉग करता है, और आपको वितरण के रूप में परिणाम देता है। आप setIntervalयह देखने के लिए कि यह अलग-अलग सेटिंग्स में कैसे चलता है , मिलिसेकंड की संख्या को बदल सकते हैं । देरी के संबंध में setTimeoutइसी तरह काम करता है setIntervalrequestAnimationFrameआमतौर पर ब्राउज़र के आधार पर 60fps के लिए चूक। यह देखने के लिए कि जब आप किसी भिन्न टैब पर स्विच करते हैं या एक निष्क्रिय विंडो होती है, तो केवल पृष्ठ खोलें, भिन्न टैब पर स्विच करें और थोड़ी देर प्रतीक्षा करें। यह एक निष्क्रिय टैब में इन कार्यों के लिए वास्तविक समय में लॉग इन करना जारी रखेगा।

टेस्ट दो

एक अन्य तरीका यह परीक्षण करने के लिए के साथ बार-बार टाइमस्टैम्प लॉग इन करने की है setIntervalऔर requestAnimationFrameऔर एक अलग कंसोल में इसे देखने के। टैब या विंडो को निष्क्रिय करते समय आप देख सकते हैं कि यह कितनी बार अपडेट किया गया है (या यदि यह कभी अपडेट हुआ है)।

परिणाम

जब क्रोम निष्क्रिय होता है तो क्रोम
क्रोम न्यूनतम setInterval1000 मीटर के अंतराल को सीमित कर देता है। यदि अंतराल 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

क्रोम के
समान फ़ायरफ़ॉक्स , फ़ायरफ़ॉक्स न्यूनतम अंतराल setIntervalको लगभग 1000ms तक सीमित करता है जब टैब (विंडो नहीं) निष्क्रिय होता है। हालांकि, requestAnimationFrameटैब के निष्क्रिय होने पर घातीय रूप से धीमी गति से चलता है, जिसमें प्रत्येक फ्रेम 1s, 2s, 4s, 8s और इसी तरह से होता है।

// 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

इंटरनेट एक्सप्लोरर
IE setIntervalटैब के निष्क्रिय होने पर देरी को सीमित नहीं करता है, लेकिन यह requestAnimationFrameनिष्क्रिय टैब में रुक जाता है। इससे कोई फर्क नहीं पड़ता कि खिड़की फ़ोकस से बाहर है या नहीं।

एज
14 से शुरू होकर, setIntervalनिष्क्रिय टैब में 1000ms पर छाया हुआ है। requestAnimationFrameहमेशा निष्क्रिय टैब में रोका जाता है।

सफारी
क्रोम की तरह, setIntervalटैब निष्क्रिय होने पर सफारी 1000ms पर कैप करता है। requestAnimationFrameरुका हुआ है।

ओपेरा
वेबकिट इंजन को अपनाने के बाद से, ओपेरा क्रोम के समान व्यवहार प्रदर्शित करता है। setInterval1000 मी पर छाया हुआ है और requestAnimationFrameटैब निष्क्रिय होने पर रुका हुआ है।

सारांश

निष्क्रिय टैब के लिए दोहराए जाने वाले अंतराल:

           setInterval      requestAnimationFrame 
Chrome
9- प्रभावित नहीं समर्थित नहीं
10 प्रभावित नहीं हुआ
11+> = 1000ms रुके

फ़ायरफ़ॉक्स
3- प्रभावित नहीं समर्थित नहीं
4 प्रभावित नहीं 1s
5+> = 1000ms 2 n s (n = निष्क्रियता के बाद से फ्रेम की संख्या)

अर्थात
9- प्रभावित नहीं समर्थित नहीं
10+ प्रभावित नहीं हुआ

धार
13- प्रभावित नहीं रोका गया
14+> = 1000ms रुके

सफारी
5- प्रभावित नहीं समर्थित नहीं
6 प्रभावित नहीं हुआ
7+> = 1000ms रुके

ओपेरा
12- प्रभावित नहीं समर्थित नहीं
15+> = 1000ms रुके

बहुत बढ़िया जवाब। के अलावा अन्य कार्यों के लिए कोई अन्य संभावित ज्ञात अंतर setIntervalऔर requestAnimationFrame?
एंड्रयू माओ

1
@AndrewMao नहीं कि मैं इससे वाकिफ हूं। मैं इस मुद्दे पर आया था जब मैं एक पुस्तकालय पर काम कर रहा था ताकि मज़बूती से पता लगाया जा सके कि जेएस के साथ फिर से जुड़ा हुआ है setIntervalया नहीं requestAnimationFrame। मैं जिस चीज के बारे में जानता हूं वह यह है कि setTimeoutसमान रूप से व्यवहार करता है setInterval, जिसमें वे दोनों फ़ायरफ़ॉक्स और क्रोम में एक ही न्यूनतम पृष्ठभूमि अंतराल रखते हैं, और अन्य ब्राउज़रों में कोई स्पष्ट सीमा नहीं है।
एंटनी

2
फ़ायरफ़ॉक्स सेटइंटरवल मिनिमम वैल्यू about:configको ब्राउज़र में url को खोलकर dom.min_background_timeout_valueऔर 1000 के अलावा किसी और चीज़ के लिए वैल्यू में बदलाव करके बदला जा सकता है।
जोनास बर्लिन

जब ब्राउज़र कम से कम 5 सेकंड के लिए पृष्ठ को पुनः लोड करने के लिए मैं इसका उपयोग कर सकता हूँ?, यहाँ मेरा सवाल है।
शाइजुत

1
ध्यान दें कि क्रोम उस दर को कम / कम नहीं करता है जिस requestAnimationFrameपर कहा जाता है यदि उपयोगकर्ता केवल एप्लिकेशन (Alt + Tab को Chrome से बाहर) स्विच करता है। जब तक क्रोम में टैब सक्रिय रहता है तब तक "फ्रेम रेट" कम या ज्यादा स्थिर रहता है।
मार्क

11

मैंने क्या देखा: क्रोम में निष्क्रिय टैब पर , आपके सभी setTimeout(एक ही होने चाहिए setInterval) प्रतीक्षा कर रहे हैं 1000 मीटर से कम 1000 मी । मुझे लगता है कि अब और टाइमआउट संशोधित नहीं हैं।

Chrome 11 और फ़ायरफ़ॉक्स 5.0 के बाद से व्यवहार प्रतीत होता है : https://developer.mozilla.org/en-US/docs/DOM/window.setTimeout#Inactive_tabs

इसके अलावा, मुझे नहीं लगता कि यह इस तरह से व्यवहार करता है जब पूरी विंडो निष्क्रिय होती है (लेकिन यह जांच करना काफी आसान है)।


1
jQuery की घटनाओं focusऔर blurटैब और विंडो स्विच दोनों का पता लगाने के लिए लगता है, इसलिए यह दोनों तरीकों से काम कर सकता है। लेकिन मुझे आश्चर्य है कि अगर यह वास्तव में दिखाई देता है या नहीं तो खिड़की कैसे पता लगाती है।
एंड्रयू माओ

2
वास्तव में इसका jQuery या जावास्क्रिप्ट के साथ कोई संबंध नहीं है क्योंकि यह आंतरिक ब्राउज़र कार्यान्वयन है।

क्या आप 2016 के अंत में इसकी पुष्टि कर सकते हैं?
vsync

0

इन्हें पूरक करने के लिए एक नया उत्तर: क्रोम 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>

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.