सेटटाइमआउट () में बचा हुआ समय ज्ञात करें?


90

मैं कुछ जावास्क्रिप्ट लिख रहा हूं जो लाइब्रेरी कोड के साथ इंटरैक्ट करता है जो मेरे पास नहीं है, और (यथोचित) परिवर्तन नहीं कर सकता। यह समय-सीमित प्रश्नों की श्रृंखला में अगले प्रश्न को दिखाने के लिए उपयोग किया जाने वाला जावास्क्रिप्ट टाइमआउट बनाता है। यह वास्तविक कोड नहीं है क्योंकि यह सभी आशाओं से परे है। यहाँ पुस्तकालय क्या कर रहा है:

....
// setup a timeout to go to the next question based on user-supplied time
var t = questionTime * 1000
test.currentTimeout = setTimeout( showNextQuestion(questions[i+1]), t );

मैं एक प्रगति बार ऑनस्क्रीन लगाना चाहता हूं जो questionTime * 1000द्वारा बनाए गए टाइमर से पूछताछ करके भरता है setTimeout। एकमात्र समस्या यह है कि ऐसा करने का कोई तरीका नहीं है। क्या कोई getTimeoutफंक्शन है जो मुझे याद आ रहा है? जावास्क्रिप्ट टाइमआउट्स की एकमात्र जानकारी जो मुझे मिल सकती है वह केवल निर्माण के माध्यम से setTimeout( function, time)और उसके माध्यम से हटाने से संबंधित हैclearTimeout( id )

मैं एक ऐसे फंक्शन की तलाश कर रहा हूं जो टाइमआउट फायर से पहले या तो बचा हुआ समय लौटाता है, या टाइमआउट के बाद समाप्त हुआ समय कहा जाता है। मेरा प्रगति बार कोड इस तरह दिखता है:

var  timeleft = getTimeout( test.currentTimeout ); // I don't know how to do this
var  $bar = $('.control .bar');
while ( timeleft > 1 ) {
    $bar.width(timeleft / test.defaultQuestionTime * 1000);
}

tl; dr: मैं एक जावास्क्रिप्ट सेटटाइमआउट () से पहले शेष समय कैसे पा सकता हूं?


यहाँ समाधान मैं अभी उपयोग कर रहा हूँ। मैं लाइब्रेरी सेक्शन के माध्यम से गया था जो परीक्षणों के प्रभारी थे, और कोड को अनियंत्रित किया (भयानक, और मेरी अनुमति के खिलाफ)।

// setup a timeout to go to the next question based on user-supplied time
var t = questionTime * 1000
test.currentTimeout = mySetTimeout( showNextQuestion(questions[i+1]), t );

और यहाँ मेरा कोड है:

// सेट टाइमआउट के लिए रैपर
फ़ंक्शन mySetTimeout (फ़ंक, टाइमआउट) {
    मध्यांतर [एन = सेटटाइमआउट (फंक, टाइमआउट)] = {
        प्रारंभ: नई तिथि ()। getTime (),
        समाप्ति: नई तिथि ()। getTime () + टाइमआउट
        टी: टाइमआउट
    }
    वापसी n;
}

यह IE 6 नहीं है किसी भी ब्राउज़र में बहुत मौके पर काम करता है। यहां तक ​​कि मूल iPhone, जहां मुझे आशा है कि चीजें अतुल्यकालिक मिलेंगी।

जवाबों:


31

यदि आप लाइब्रेरी कोड को संशोधित नहीं कर सकते हैं, तो आपको अपने उद्देश्यों के अनुरूप सेटटाइमआउट को फिर से परिभाषित करना होगा। यहाँ एक उदाहरण है कि आप क्या कर सकते हैं:

(function () {
var nativeSetTimeout = window.setTimeout;

window.bindTimeout = function (listener, interval) {
    function setTimeout(code, delay) {
        var elapsed = 0,
            h;

        h = window.setInterval(function () {
                elapsed += interval;
                if (elapsed < delay) {
                    listener(delay - elapsed);
                } else {
                    window.clearInterval(h);
                }
            }, interval);
        return nativeSetTimeout(code, delay);
    }

    window.setTimeout = setTimeout;
    setTimeout._native = nativeSetTimeout;
};
}());
window.bindTimeout(function (t) {console.log(t + "ms remaining");}, 100);
window.setTimeout(function () {console.log("All done.");}, 1000);

यह उत्पादन कोड नहीं है, लेकिन यह आपको सही रास्ते पर लाना चाहिए। ध्यान दें कि आप प्रति टाइमआउट केवल एक श्रोता को बाँध सकते हैं। मैंने इसके साथ व्यापक परीक्षण नहीं किया है, लेकिन यह फायरबग में काम करता है।

एक अधिक मजबूत समाधान रैपिंग टाइमटाइमआउट की एक ही तकनीक का उपयोग करेगा, लेकिन बदले में दिए गए टाइमआउट से एक मानचित्र का उपयोग करें। श्रोताओं को प्रति समय कई श्रोताओं को संभालने के लिए श्रोताओं से। यदि आप समय समाप्त हो गया है तो आप अपने श्रोता को लपेटने पर विचार कर सकते हैं ताकि आप अपने श्रोता को अलग कर सकें।


धन्यवाद, आपने मेरा दिन बचा लिया!
xecutioner

14
निष्पादन समय के कारण, थोड़ी देर में कुछ मिलीसेकेंड तक बहाव हो सकता है। ऐसा करने का एक अधिक सुरक्षित तरीका, उस समय को रिकॉर्ड करता है जब आपने टाइमआउट (नई तिथि ()) शुरू किया था और फिर इसे वर्तमान समय (दूसरी नई तिथि ()) से घटाया
जोनाथन

61

सिर्फ रिकॉर्ड के लिए, नोड में बचे हुए समय को पाने का एक तरीका है। js:

var timeout = setTimeout(function() {}, 3600 * 1000);

setInterval(function() {
    console.log('Time left: '+getTimeLeft(timeout)+'s');
}, 2000);

function getTimeLeft(timeout) {
    return Math.ceil((timeout._idleStart + timeout._idleTimeout - Date.now()) / 1000);
}

प्रिंटों:

$ node test.js 
Time left: 3599s
Time left: 3597s
Time left: 3595s
Time left: 3593s

यह फ़ायरफ़ॉक्स के माध्यम से काम करने के लिए प्रतीत नहीं होता है, लेकिन चूंकि नोड.जेएस जावास्क्रिप्ट है, मैंने सोचा कि यह टिप्पणी नोड समाधान की तलाश में लोगों के लिए उपयोगी हो सकती है।


5
निश्चित नहीं है कि यह नोड का नया संस्करण है या क्या लेकिन इसके लिए काम करने के लिए मुझे "गेटटाइम ()" भाग को हटाना पड़ा। ऐसा लगता है कि _idleStart पहले से ही अब पूर्णांक है
kasztelan

3
मैंने इसे केवल नोड 0.10 में आज़माया getTime()है, हटा दिया गया है, _idleStartपहले से ही समय है
टैन गुयेन

2
नोड 6.3 पर काम न करें, क्योंकि टाइमआउट संरचना उन सूचनाओं का रिसाव है।
हुआन

53

संपादित करें: मुझे वास्तव में लगता है कि मैंने एक और भी बेहतर बनाया: https://stackoverflow.com/a/36389263/2378102

मैंने यह फ़ंक्शन लिखा है और मैं इसका बहुत उपयोग करता हूं:

function timer(callback, delay) {
    var id, started, remaining = delay, running

    this.start = function() {
        running = true
        started = new Date()
        id = setTimeout(callback, remaining)
    }

    this.pause = function() {
        running = false
        clearTimeout(id)
        remaining -= new Date() - started
    }

    this.getTimeLeft = function() {
        if (running) {
            this.pause()
            this.start()
        }

        return remaining
    }

    this.getStateRunning = function() {
        return running
    }

    this.start()
}

टाइमर बनाएं:

a = new timer(function() {
    // What ever
}, 3000)

इसलिए यदि आप चाहते हैं कि समय शेष रहे:

a.getTimeLeft()

उसके लिए धन्यवाद। बिल्कुल नहीं जो मैं देख रहा हूं, लेकिन समय को गिनने के लिए कार्य बहुत उपयोगी है
बजाय

4

जावास्क्रिप्ट की घटना के ढेर आप कैसे सोचते हैं काम नहीं करते हैं।

जब कोई टाइमआउट ईवेंट बनाया जाता है, तो इसे ईवेंट कतार में जोड़ा जाता है, लेकिन अन्य ईवेंट प्राथमिकता ले सकते हैं जबकि उस ईवेंट को निकाल दिया जा रहा है, निष्पादन समय में देरी और रनटाइम स्थगित कर रहा है।

उदाहरण: आप स्क्रीन पर किसी चीज़ को अलर्ट करने के लिए 10 सेकंड की देरी के साथ एक टाइमआउट बनाते हैं। इसे इवेंट स्टैक में जोड़ा जाएगा और सभी वर्तमान घटनाओं को निकाल दिए जाने के बाद निष्पादित किया जाएगा (कुछ देरी का कारण)। फिर, जब टाइमआउट संसाधित किया जाता है, तो ब्राउज़र अभी भी अन्य घटनाओं पर कब्जा करने के लिए उन्हें स्टैक में जोड़ता है, जो प्रसंस्करण में और देरी का कारण बनता है। यदि उपयोगकर्ता क्लिक करता है, या बहुत सारे ctrl + टाइपिंग करता है, तो उनकी घटनाएं वर्तमान स्टैक पर प्राथमिकता लेती हैं। आपके 10 सेकंड 15 सेकंड, या उससे अधिक समय में बदल सकते हैं।


कहा जा रहा है कि, नकली करने के कई तरीके हैं कितना समय बीत चुका है। एक तरीका यह है कि आप setTimeout को स्टैक में जोड़ने के बाद एक setInterval को निष्पादित करें।

उदाहरण: 10 सेकंड की देरी (एक वैश्विक में देरी करने वाली दुकान) के साथ एक समझौता करें। फिर एक सेट इन्टरवल करें जो हर सेकंड को देरी से 1 घटाता है और शेष देरी को आउटपुट करता है। इस वजह से कि ईवेंट स्टैक वास्तविक समय (ऊपर वर्णित) को कैसे प्रभावित कर सकता है, यह अभी भी सटीक नहीं होगा, लेकिन एक गिनती देता है।


संक्षेप में, शेष समय प्राप्त करने का कोई वास्तविक तरीका नहीं है। उपयोगकर्ता के लिए केवल अनुमान लगाने और उसे व्यक्त करने के तरीके हैं।


4

सर्वर साइड Node.js विशिष्ट

उपरोक्त में से कोई भी वास्तव में मेरे लिए काम नहीं करता था, और टाइमआउट ऑब्जेक्ट का निरीक्षण करने के बाद ऐसा लगता था कि जब प्रक्रिया शुरू हुई तो सब कुछ सापेक्ष था। निम्नलिखित ने मेरे लिए काम किया:

myTimer = setTimeout(function a(){console.log('Timer executed')},15000);

function getTimeLeft(timeout){
  console.log(Math.ceil((timeout._idleStart + timeout._idleTimeout)/1000 - process.uptime()));
}

setInterval(getTimeLeft,1000,myTimer);

आउटपुट:

14
...
3
2
1
Timer executed
-0
-1
...

node -v
v9.11.1

संक्षिप्तता के लिए संपादित आउटपुट, लेकिन यह मूल फ़ंक्शन निष्पादन या निष्पादन के बाद तक लगभग अनुमानित समय देता है। जैसा कि अन्य उल्लेख करते हैं, नोड प्रक्रियाओं में से कोई भी सटीक नहीं होगा, लेकिन अगर मैं एक अनुरोध को दबा देना चाहता हूं जो 1 मिनट से कम समय पहले चला था, और मैंने टाइमर को संग्रहीत किया, तो मुझे नहीं लगता कि यह क्यों होगा एक त्वरित जाँच के रूप में काम करें। 10.2+ में रिफ्रेशर के साथ ऑब्जेक्ट्स को टकराना दिलचस्प हो सकता है।


1

आप प्रत्येक टाइमआउट के अंत समय को एक नक्शे में संग्रहीत करने के setTimeout लिए संशोधित कर सकते हैं और getTimeoutएक निश्चित आईडी के साथ टाइमआउट के लिए बचे हुए समय को प्राप्त करने के लिए एक फ़ंक्शन बना सकते हैं।

यह सुपर का समाधान था , लेकिन मैंने इसे थोड़ा कम मेमोरी का उपयोग करने के लिए संशोधित किया

let getTimeout = (() => { // IIFE
    let _setTimeout = setTimeout, // Reference to the original setTimeout
        map = {}; // Map of all timeouts with their end times

    setTimeout = (callback, delay) => { // Modify setTimeout
        let id = _setTimeout(callback, delay); // Run the original, and store the id
        map[id] = Date.now() + delay; // Store the end time
        return id; // Return the id
    };

    return (id) => { // The actual getTimeout function
        // If there was no timeout with that id, return NaN, otherwise, return the time left clamped to 0
        return map[id] ? Math.max(map[id] - Date.now(), 0) : NaN;
    }
})();

उपयोग:

// go home in 4 seconds
let redirectTimeout = setTimeout(() => {
    window.location.href = "/index.html";
}, 4000);

// display the time left until the redirect
setInterval(() => {
    document.querySelector("#countdown").innerHTML = `Time left until redirect ${getTimeout(redirectTimeout)}`;
},1);

यहाँ इस getTimeout IIFE का एक छोटा संस्करण है :

let getTimeout=(()=>{let t=setTimeout,e={};return setTimeout=((a,o)=>{let u=t(a,o);return e[u]=Date.now()+o,u}),t=>e[t]?Math.max(e[t]-Date.now(),0):NaN})();

मुझे आशा है कि यह आपके लिए उतना ही उपयोगी है जितना कि यह मेरे लिए था! :)


0

नहीं, लेकिन आपके पास अपने फ़ंक्शन में एनीमेशन के लिए अपना स्वयं का सेटटाइमआउट / सेटइंटरवल हो सकता है।

अपना प्रश्न इस तरह से कहें:

function myQuestion() {
  // animate the progress bar for 1 sec
  animate( "progressbar", 1000 );

  // do the question stuff
  // ...
}

और आपके एनीमेशन को इन 2 कार्यों द्वारा संभाला जाएगा:

function interpolate( start, end, pos ) {
  return start + ( pos * (end - start) );
}

function animate( dom, interval, delay ) {

      interval = interval || 1000;
      delay    = delay    || 10;

  var start    = Number(new Date());

  if ( typeof dom === "string" ) {
    dom = document.getElementById( dom );
  }

  function step() {

    var now     = Number(new Date()),
        elapsed = now - start,
        pos     = elapsed / interval,
        value   = ~~interpolate( 0, 500, pos ); // 0-500px (progress bar)

    dom.style.width = value + "px";

    if ( elapsed < interval )
      setTimeout( step, delay );
  }

  setTimeout( step, delay );
}

अच्छी तरह से अंतर केवल एमएस में मापा जा सकता है, क्योंकि एनीमेशन आपके फ़ंक्शन के शीर्ष पर शुरू होता है। मैंने देखा कि आप jQuery का उपयोग करते हैं। आप jquery.animate का उपयोग कर सकते हैं।
gblazex

सबसे अच्छा तरीका है कि आप इसे अपने लिए देखें और देखें। :)
gblazex

0

अगर किसी की नजर इस पर पड़ती है। मैं एक टाइमआउट और अंतराल प्रबंधक के साथ आया हूं जो आपको टाइमआउट या अंतराल में बचे हुए समय के साथ-साथ कुछ अन्य सामान भी दे सकता है। मैं इसे और अधिक स्पष्ट और अधिक सटीक बनाने के लिए जोड़ रहा हूँ, लेकिन यह काफी अच्छी तरह से काम करने लगता है (हालाँकि मेरे पास इसे और अधिक सटीक बनाने के लिए कुछ और विचार हैं):

https://github.com/vhmth/Tock


आपके लिंक टूट गए हैं
किक बटोस्की

0

प्रश्न का उत्तर पहले ही दिया जा चुका है, लेकिन मैं थोड़ा सा जोड़ूंगा। यह सिर्फ मेरे लिए हुआ।

का प्रयोग करें setTimeoutमें recursionइस प्रकार है:

var count = -1;

function beginTimer()
{
    console.log("Counting 20 seconds");
    count++;

    if(count <20)
    {
        console.log(20-count+"seconds left");
        setTimeout(beginTimer,2000);
    }
    else
    {
        endTimer();
    }
}

function endTimer()
{
    console.log("Time is finished");
}

मुझे लगता है कि कोड स्वयं व्याख्यात्मक है


0

इसे जाँचें:

class Timer {
  constructor(fun,delay) {
    this.timer=setTimeout(fun, delay)
    this.stamp=new Date()
  }
  get(){return ((this.timer._idleTimeout - (new Date-this.stamp))/1000) }
  clear(){return (this.stamp=null, clearTimeout(this.timer))}
}

टाइमर बनाएं:

let smtg = new Timer(()=>{do()}, 3000})

बने रहें:

smth.get()

समय समाप्त करें

smth.clear()

0
    (function(){
        window.activeCountdowns = [];
        window.setCountdown = function (code, delay, callback, interval) {
            var timeout = delay;
            var timeoutId = setTimeout(function(){
                clearCountdown(timeoutId);
                return code();
            }, delay);
            window.activeCountdowns.push(timeoutId);
            setTimeout(function countdown(){
                var key = window.activeCountdowns.indexOf(timeoutId);
                if (key < 0) return;
                timeout -= interval;
                setTimeout(countdown, interval);
                return callback(timeout);
            }, interval);
            return timeoutId;
        };
        window.clearCountdown = function (timeoutId) {
            clearTimeout(timeoutId);
            var key = window.activeCountdowns.indexOf(timeoutId);
            if (key < 0) return;
            window.activeCountdowns.splice(key, 1);
        };
    })();

    //example
    var t = setCountdown(function () {
        console.log('done');
    }, 15000, function (i) {
        console.log(i / 1000);
    }, 1000);

0

मैं यहाँ इस जवाब की तलाश में रुक गया, लेकिन अपनी समस्या से उबर रहा था। यदि आप यहां हैं क्योंकि आपको सेटटाइमआउट करते समय केवल समय का ध्यान रखने की आवश्यकता है, तो यह करने का एक और तरीका है:

    var focusTime = parseInt(msg.time) * 1000

    setTimeout(function() {
        alert('Nice Job Heres 5 Schrute bucks')
        clearInterval(timerInterval)
    }, focusTime)

    var timerInterval = setInterval(function(){
        focusTime -= 1000
        initTimer(focusTime / 1000)
    }, 1000);

0

एक तेज, आसान तरीका:

tmo = 1000;
start = performance.now();
setTimeout(function(){
    foo();
},tmo);

आप इसके साथ शेष समय प्राप्त कर सकते हैं:

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