2014-04-11 11 views
8

सरल कार्य बनाते समय मुझे निम्नलिखित समस्या का सामना करना पड़ा: वेबकिट इंजन का उपयोग करके एचटीएमएल घड़ी प्रदर्शित करना। सिस्टम आवश्यकता परिवर्तन को संभालने के लिए अतिरिक्त आवश्यकता थी और इसे विंडोज़ पर काम करना चाहिए। मैंने इसे एंटर करने के लिए setInterval का उपयोग किया है, लेकिन जब मैं सिस्टम समय को पिछड़ा करता हूं तो ब्राउज़र को फ्रीज करना प्रतीत होता है। मेरे लिए यह वेबकिट मुद्दे की तरह दिखता है। यह इस सरल कोड चलाकर सफारी पर पुन: पेश करने के लिए आसान है:वेबकिट सेट इंटरवल और सिस्टम समय परिवर्तन

<p id="date"></p> 
setInterval(SetTime, 1000); 
function SetTime() { 
document.getElementById('date').textContent=new Date(); 
} 

मैं पुनरावर्ती setTimeout कॉल के साथ एक और दृष्टिकोण बना दिया है उसके बाद। वही प्रभाव

(function loop() { 
document.getElementById('date').textContent=new Date(); 
setTimeout(loop, 1000); 
})(); 

कोई विचार क्यों हो रहा है और इसके आसपास कैसे जाना है?

उत्तर

2

यह लगभग निश्चित रूप से वेबकिट के साथ एक मुद्दा है।

समस्या

जब आप setTimeout उपयोग करते हैं, तो आपके पास दो गुणों के साथ एक 'घड़ी' बनाने:

  • एक टाइमस्टैम्प, अब निर्दिष्ट देरी
  • एक कॉलबैक + करने के लिए सेट सिस्टम टाइम टाइम टाइमस्टैम्प से अधिक होने के बाद एक बार आग लगाना।

आप कुछ इस तरह देख setTimeout की एक सीधी सादी कार्यान्वयन कल्पना कर सकते हैं:

var timers = []; 
function setTimeout(callback, delay) { 
    var id = timers.length; 
    timers[id] = { 
     callback: callback, 
     timestamp: Date.now() + delay 
    } 
    return id; 
} 

यह केवल एक टाइमर बना सकते हैं और एक सूची में जोड़ने जाएगा। फिर, प्रत्येक टिक पर, जे एस क्रम इन टाइमर की जाँच करें और अमल होगा उन लोगों के लिए कॉलबैक कि सक्रिय नहीं हो:

var now = Date.now(); 
for(var id in timers) { 
    var timer = timers[id]; 
    if(timer && timer.timestamp < now) { 
     callback(); 
     delete timers[id]; 
    } 
} 

इस कार्यान्वयन को देखते हुए, एक करने के लिए बदल रहा है सिस्टम का समय (यानी कि उपरोक्त उदाहरण में Date.now()) अब कल्पना अतीत में मूल्य - टाइमर का टाइमस्टैम्प अभी भी पिछले सिस्टम समय (यानी भविष्य में) के सापेक्ष सेट किया जाएगा।

एक ही समस्या setInterval के साथ मौजूद है, जो (वेबकिट में सेन कोड मानते हुए) setTimeout का उपयोग करके कार्यान्वित किया जाएगा।

दुर्भाग्य से, इसका मतलब है कि setTimeout या setInterval के किसी भी मंगलाचरण पीड़ित जा रहा है।

समाधान

एक विकल्प के रूप में, आप प्रत्येक टिक पर एक कॉलबैक प्रदर्शन करने के लिए सुंदर window.requestAnimationFrame विधि का उपयोग कर सकते हैं। मैंने इसका बिल्कुल परीक्षण नहीं किया है, लेकिन सिस्टम के समय के बावजूद इसे प्रत्येक टिक पर आग लगाना चाहिए।

बोनस के रूप में, प्रत्येक बार जब यह कॉलबैक को फायर करता है, तो आप वर्तमान टाइमस्टैम्प को पैरामीटर के रूप में पारित कर देते हैं।पिछले टाइमस्टैम्प अपने कॉलबैक के लिए पारित का ट्रैक रखने करके, आप आसानी प्रणाली समय परिवर्तन पीछे की ओर का पता लगा सकता:

var lastTimestamp; 
var onNextFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame; 

var checkForPast = function(timestamp) { 
    if(lastTimestamp && timestamp < lastTimestamp) { 
     console.error('System time moved into the past! I should probably handle this'); 
    } 
    lastTimestamp = timestamp; 
    onNextFrame(checkForPast); 
}; 

onNextFrame(checkForPast); 

निष्कर्ष

यह आप के लिए अच्छी खबर नहीं हो सकता है, लेकिन आप शायद अपने पूरे आवेदन को फिर से लिखने चाहिए requestAnimationFrame का उपयोग करने के लिए - यह आपकी आवश्यकताओं के लिए अधिक उपयुक्त लगता है:

var onNextFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame; 
var dateElem = document.getElementById('date'); 

var updateDate = function(timestamp) { 
    dateElem.textContent = new Date(); 
    onNextFrame(updateDate); 
}; 
onNextFrame(updateDate); 
+0

धन्यवाद जिम। मैं आपके समाधान का प्रयास करूंगा। मैंने पहले ही इस मुद्दे को वेबकिट टीम को रिपोर्ट कर दी है। – Sleipnir

+0

सेवा की खुशी है। अगर यह काम करता है तो कृपया मुझे बताएं (और अगर ऐसा है तो जवाब स्वीकार करें)! –

संबंधित मुद्दे