जावास्क्रिप्ट: विराम सेटटाइमआउट ();


119

अगर मेरे पास एक सक्रिय टाइमआउट चल रहा है var t = setTimeout("dosomething()", 5000), जिसके माध्यम से सेट किया गया था ,

क्या इसे रोकने और फिर से शुरू करने के लिए कुछ भी है?


क्या वर्तमान समय में शेष समय पाने का कोई तरीका है?
या क्या मुझे एक वैरिएबल में है, जब टाइमआउट सेट किया गया है, तो वर्तमान समय को स्टोर करें, फिर हम रोकते हैं, अब और फिर के बीच अंतर प्राप्त करते हैं?


1
उन लोगों के लिए जो सोच रहे हैं, रोकना उदाहरण के लिए है: एक div को 5 सेकंड में गायब करने के लिए सेट किया जाता है, 3 सेकंड (इसलिए 2 सेकंड शेष) div पर उपयोगकर्ता पति, आप टाइमआउट को रोकते हैं, जब उपयोगकर्ता div बंद कर देता है। आप इसे फिर से शुरू करते हैं, 2 सेकंड बाद यह गायब हो जाता है।
हेलवुड

जवाबों:


260

आप window.setTimeoutइस तरह से लपेट सकते हैं , जो मुझे लगता है कि आप सवाल में सुझाव दे रहे हैं के समान है:

var Timer = function(callback, delay) {
    var timerId, start, remaining = delay;

    this.pause = function() {
        window.clearTimeout(timerId);
        remaining -= Date.now() - start;
    };

    this.resume = function() {
        start = Date.now();
        window.clearTimeout(timerId);
        timerId = window.setTimeout(callback, remaining);
    };

    this.resume();
};

var timer = new Timer(function() {
    alert("Done!");
}, 1000);

timer.pause();
// Do some stuff...
timer.resume();

3
@yart: वापस लुढ़का, माफ करना। यह एक अच्छा अतिरिक्त है सिवाय इसके कि अतिरिक्त मानकों को जोड़ने के लिए setTimeout()Internet Explorer में काम नहीं करता है <= 9.
टिम डाउन

4
यदि आप करते हैं तो timer.resume(); timer.resume();आप समानांतर में दो टाइमआउट करेंगे। यही कारण है कि आप फिर से शुरू की शुरुआत में clearTimeout(timerId)या तो पहले या if (timerId) return;शॉर्ट सर्किट करना चाहेंगे ।
कर्नेल

2
अरे, मुझे यह उत्तर पसंद आया, लेकिन मुझे खींचना पड़ा: var timerId, start, remaining;क्लास के दायरे से बाहर और remaining = delay;पैरामीटर को पकड़ने के लिए वापस अंदर जोड़ें । एक आकर्षण की तरह काम करता है!
3

1
@ जोश 979: आपको वास्तव में ऐसा करने की आवश्यकता नहीं है और यह एक बुरा विचार है, क्योंकि यह उन चरों को उजागर करता है जो आंतरिक होने चाहिए। हो सकता है कि आपने किसी ब्लॉक (जैसे अंदर if (blah) { ... }) या किसी चीज़ के अंदर कोड पेस्ट किया हो ?
टिम डाउन

1
किसी कारण से यह केवल एक बार शुरू होने के बाद मेरे लिए चलता है।
पीटरक्स

17

कुछ इस तरह से करना चाहिए ट्रिक

function Timer(fn, countdown) {
    var ident, complete = false;

    function _time_diff(date1, date2) {
        return date2 ? date2 - date1 : new Date().getTime() - date1;
    }

    function cancel() {
        clearTimeout(ident);
    }

    function pause() {
        clearTimeout(ident);
        total_time_run = _time_diff(start_time);
        complete = total_time_run >= countdown;
    }

    function resume() {
        ident = complete ? -1 : setTimeout(fn, countdown - total_time_run);
    }

    var start_time = new Date().getTime();
    ident = setTimeout(fn, countdown);

    return { cancel: cancel, pause: pause, resume: resume };
}

मैं तब +new Date()से बदल गया new Date().getTime()जब से यह तेज है: jsperf.com/date-vs-gettime
yckart

9

नहीं, आपको इसे रद्द करने की आवश्यकता होगी ( clearTimeout), उस समय को मापें जब आपने इसे शुरू किया था और नए समय के साथ इसे फिर से शुरू करें।


7

टिम Downs के एक थोड़ा संशोधित संस्करण जवाब । हालाँकि, जब से टिम ने मेरा संपादन वापस किया है, मुझे इसका जवाब खुद देना होगा। मेरा समाधान argumentsतीसरे (3, 4, 5 ...) पैरामीटर के रूप में अतिरिक्त उपयोग करना और टाइमर साफ़ करना संभव बनाता है :

function Timer(callback, delay) {
    var args = arguments,
        self = this,
        timer, start;

    this.clear = function () {
        clearTimeout(timer);
    };

    this.pause = function () {
        this.clear();
        delay -= new Date() - start;
    };

    this.resume = function () {
        start = new Date();
        timer = setTimeout(function () {
            callback.apply(self, Array.prototype.slice.call(args, 2, args.length));
        }, delay);
    };

    this.resume();
}

जैसा कि टिम ने उल्लेख किया है, अतिरिक्त पैरामीटर उपलब्ध नहीं हैं IE lt 9, हालांकि मैंने थोड़ा सा काम किया है ताकि यह भी काम करे oldIE

उपयोग: new Timer(Function, Number, arg1, arg2, arg3...)

function callback(foo, bar) {
    console.log(foo); // "foo"
    console.log(bar); // "bar"
}

var timer = new Timer(callback, 1000, "foo", "bar");

timer.pause();
document.onclick = timer.resume;

6

"रोकें" और "फिर से शुरू" वास्तव में बहुत मायने नहीं रखते हैं setTimeout, जो कि एक बंद चीज है। क्या आपका मतलब है setInterval? यदि ऐसा है, तो नहीं, आप इसे रोक नहीं सकते, आप इसे केवल रद्द कर सकते हैं ( clearInterval) और फिर इसे फिर से शेड्यूल करें। कल्पना के टाइमर अनुभाग में इन सभी का विवरण ।

// Setting
var t = setInterval(doSomething, 1000);

// Pausing (which is really stopping)
clearInterval(t);
t = 0;

// Resuming (which is really just setting again)
t = setInterval(doSomething, 1000);

16
सेटटाइमआउट के संदर्भ में, ठहराव और फिर से शुरू करना अभी भी समझ में आता है।
dbkaplun

6

टाइमआउट काफी आसान था, जिसके लिए एक समाधान खोजना था, लेकिन इंटरवल थोड़ा मुश्किल था।

मैं इस मुद्दे को हल करने के लिए निम्नलिखित दो वर्गों के साथ आया:

function PauseableTimeout(func, delay){
    this.func = func;

    var _now = new Date().getTime();
    this.triggerTime = _now + delay;

    this.t = window.setTimeout(this.func,delay);

    this.paused_timeLeft = 0;

    this.getTimeLeft = function(){
        var now = new Date();

        return this.triggerTime - now;
    }

    this.pause = function(){
        this.paused_timeLeft = this.getTimeLeft();

        window.clearTimeout(this.t);
        this.t = null;
    }

    this.resume = function(){
        if (this.t == null){
            this.t = window.setTimeout(this.func, this.paused_timeLeft);
        }
    }

    this.clearTimeout = function(){ window.clearTimeout(this.t);}
}

function PauseableInterval(func, delay){
    this.func = func;
    this.delay = delay;

    this.triggerSetAt = new Date().getTime();
    this.triggerTime = this.triggerSetAt + this.delay;

    this.i = window.setInterval(this.func, this.delay);

    this.t_restart = null;

    this.paused_timeLeft = 0;

    this.getTimeLeft = function(){
        var now = new Date();
        return this.delay - ((now - this.triggerSetAt) % this.delay);
    }

    this.pause = function(){
        this.paused_timeLeft = this.getTimeLeft();
        window.clearInterval(this.i);
        this.i = null;
    }

    this.restart = function(sender){
        sender.i = window.setInterval(sender.func, sender.delay);
    }

    this.resume = function(){
        if (this.i == null){
            this.i = window.setTimeout(this.restart, this.paused_timeLeft, this);
        }
    }

    this.clearInterval = function(){ window.clearInterval(this.i);}
}

इन्हें इस प्रकार लागू किया जा सकता है:

var pt_hey = new PauseableTimeout(function(){
    alert("hello");
}, 2000);

window.setTimeout(function(){
    pt_hey.pause();
}, 1000);

window.setTimeout("pt_hey.start()", 2000);

यह उदाहरण एक रुकने योग्य टाइमआउट (pt_hey) को सेट करेगा जो दो सेकंड के बाद "हे" चेतावनी के लिए निर्धारित है। एक और टाइमआउट एक सेकंड के बाद pt_hey को रोक देता है। एक तीसरा टाइमआउट दो सेकंड के बाद pt_hey को फिर से शुरू करता है। pt_hey एक सेकंड के लिए चलता है, एक सेकंड के लिए रुकता है, फिर दौड़ना शुरू करता है। pt_hey तीन सेकंड के बाद चलाता है।

अब ट्रिकियर अंतराल के लिए

var pi_hey = new PauseableInterval(function(){
    console.log("hello world");
}, 2000);

window.setTimeout("pi_hey.pause()", 5000);

window.setTimeout("pi_hey.resume()", 6000);

यह उदाहरण हर दो सेकंड में कंसोल में "हैलो वर्ल्ड" लिखने के लिए एक पॉज़ेबल इंटरवल (pi_hey) सेट करता है। एक टाइमआउट पाँच सेकंड के बाद pi_hey को रोक देता है। एक और टाइमआउट छह सेकंड के बाद pi_hey को फिर से शुरू करता है। तो pi_hey दो बार ट्रिगर करेगा, एक सेकंड के लिए चलाएगा, एक सेकंड के लिए पॉज़ करेगा, एक सेकंड के लिए चलाएगा और फिर हर 2 सेकंड पर ट्रिगर करता रहेगा।

अन्य कार्य

  • clearTimeout () और clearInterval ()

    pt_hey.clearTimeout();और pi_hey.clearInterval();टाइमआउट और अंतराल को साफ़ करने के लिए एक आसान तरीका है।

  • getTimeLeft ()

    pt_hey.getTimeLeft();और pi_hey.getTimeLeft();अगले ट्रिगर होने तक कितने मिलीसेकंड वापस आ जाएगा।


क्या आप अपने विचारों की व्याख्या कर सकते हैं, हमें एक को थामने के लिए एक जटिल वर्ग की आवश्यकता क्यों है setInterval? मुझे लगता है कि एक सरल if(!true) return;चाल करेगा, या मैं गलत हूं?
यार्कर्ट

2
मैंने इसे ऐसा बनाया है कि जब आप इसे ट्रिगर करते हैं तो कॉल को छोड़ देने के बजाय आप सचमुच अंतराल को रोक सकते हैं। यदि किसी गेम में, प्रत्येक 60 सेकंड में एक पावर-अप जारी किया जाता है, और मैं गेम को रोक देता हूं, इससे पहले कि यह ट्रिगर करने वाला है, आपकी पद्धति का उपयोग करते हुए, मुझे एक और पावर-अप के लिए एक मिनट का इंतजार करना होगा। यह वास्तव में रुकने वाला नहीं है, यह सिर्फ एक कॉल की अनदेखी है। इसके बजाय, मेरा तरीका वास्तव में रुक रहा है, और इसलिए, पावर-अप को गेम-प्ले के संबंध में 'ऑन-टाइम' जारी किया गया है।
theCrzyMan

2

मुझे प्रगति-बार दिखाने के लिए बीते हुए और शेष समय की गणना करने की आवश्यकता थी। स्वीकृत उत्तर का उपयोग करना आसान नहीं था। 'setInterval' इस कार्य के लिए 'setTimeout' से बेहतर है। इसलिए, मैंने इस टाइमर क्लास को बनाया जिसे आप किसी भी प्रोजेक्ट में उपयोग कर सकते हैं।

https://jsfiddle.net/ashraffayad/t0mmv853/

'use strict';


    //Constructor
    var Timer = function(cb, delay) {
      this.cb = cb;
      this.delay = delay;
      this.elapsed = 0;
      this.remaining = this.delay - self.elapsed;
    };

    console.log(Timer);

    Timer.prototype = function() {
      var _start = function(x, y) {
          var self = this;
          if (self.elapsed < self.delay) {
            clearInterval(self.interval);
            self.interval = setInterval(function() {
              self.elapsed += 50;
              self.remaining = self.delay - self.elapsed;
              console.log('elapsed: ' + self.elapsed, 
                          'remaining: ' + self.remaining, 
                          'delay: ' + self.delay);
              if (self.elapsed >= self.delay) {
                clearInterval(self.interval);
                self.cb();
              }
            }, 50);
          }
        },
        _pause = function() {
          var self = this;
          clearInterval(self.interval);
        },
        _restart = function() {
          var self = this;
          self.elapsed = 0;
          console.log(self);
          clearInterval(self.interval);
          self.start();
        };

      //public member definitions
      return {
        start: _start,
        pause: _pause,
        restart: _restart
      };
    }();


    // - - - - - - - - how to use this class

    var restartBtn = document.getElementById('restart');
    var pauseBtn = document.getElementById('pause');
    var startBtn = document.getElementById('start');

    var timer = new Timer(function() {
      console.log('Done!');
    }, 2000);

    restartBtn.addEventListener('click', function(e) {
      timer.restart();
    });
    pauseBtn.addEventListener('click', function(e) {
      timer.pause();
    });
    startBtn.addEventListener('click', function(e) {
      timer.start();
    });

2

/ पुनर्जीवित

ES6 वर्जन क्लास-वाई सिंथैटिक शुगर 💋 का उपयोग कर रहा है

(थोड़ा-संशोधित: जोड़ा प्रारंभ ())

class Timer {
  constructor(callback, delay) {
    this.callback = callback
    this.remainingTime = delay
    this.startTime
    this.timerId
  }

  pause() {
    clearTimeout(this.timerId)
    this.remainingTime -= new Date() - this.startTime
  }

  resume() {
    this.startTime = new Date()
    clearTimeout(this.timerId)
    this.timerId = setTimeout(this.callback, this.remainingTime)
  }

  start() {
    this.timerId = setTimeout(this.callback, this.remainingTime)
  }
}

// supporting code
const pauseButton = document.getElementById('timer-pause')
const resumeButton = document.getElementById('timer-resume')
const startButton = document.getElementById('timer-start')

const timer = new Timer(() => {
  console.log('called');
  document.getElementById('change-me').classList.add('wow')
}, 3000)

pauseButton.addEventListener('click', timer.pause.bind(timer))
resumeButton.addEventListener('click', timer.resume.bind(timer))
startButton.addEventListener('click', timer.start.bind(timer))
<!doctype html>
<html>
<head>
  <title>Traditional HTML Document. ZZz...</title>
  <style type="text/css">
    .wow { color: blue; font-family: Tahoma, sans-serif; font-size: 1em; }
  </style>
</head>
<body>
  <h1>DOM &amp; JavaScript</h1>

  <div id="change-me">I'm going to repaint my life, wait and see.</div>

  <button id="timer-start">Start!</button>
  <button id="timer-pause">Pause!</button>
  <button id="timer-resume">Resume!</button>
</body>
</html>


1

आप ClearTimeout () में देख सकते हैं

या किसी निश्चित स्थिति की चपेट में आने पर सेट किए गए वैश्विक चर पर निर्भर करता है। जैसे एक बटन दबाया जाता है।

  <button onclick="myBool = true" > pauseTimeout </button>

  <script>
  var myBool = false;

  var t = setTimeout(function() {if (!mybool) {dosomething()}}, 5000);
  </script>

1

आप इसे घटनाओं के साथ भी लागू कर सकते हैं।

समय के अंतर की गणना करने के बजाय, आप एक 'टिक' घटना को सुनना और शुरू करना बंद कर देते हैं जो पृष्ठभूमि में चलती रहती है:

var Slideshow = {

  _create: function(){                  
    this.timer = window.setInterval(function(){
      $(window).trigger('timer:tick'); }, 8000);
  },

  play: function(){            
    $(window).bind('timer:tick', function(){
      // stuff
    });       
  },

  pause: function(){        
    $(window).unbind('timer:tick');
  }

};

1

यदि आप किसी भी तरह jquery का उपयोग कर रहे हैं, तो $ .doTimeout देखें प्लगइन देखें। यह बात सेट टाइमआउट पर एक बहुत बड़ा सुधार है, जिसमें आपको एक स्ट्रिंग स्ट्रिंग के साथ अपने समय-आउट का ट्रैक रखने की सुविधा है, जिसे आप निर्दिष्ट करते हैं और जो आपके द्वारा सेट किए जाने पर हर बार नहीं बदलता है, और आसान रद्द करना, मतदान छोरों और डिबॉन्सेसिंग को लागू करना, और अधिक। मेरे सबसे अधिक उपयोग किए जाने वाले जेकरी प्लगइन्स में से एक।

दुर्भाग्य से, यह बॉक्स से बाहर रुकने / फिर से शुरू करने का समर्थन नहीं करता है। इसके लिए, आपको $ .doTimeout को लपेटने या विस्तारित करने की आवश्यकता होगी, संभवतः स्वीकृत उत्तर के समान।


मैं उम्मीद कर रहा था कि doTimeout में पॉज़ / रिज्यूमे होगा, लेकिन मैं इसे तब नहीं देख रहा हूं, जब पूरे डॉक्यूमेंटेशन, उदाहरणों और लूपिंग सोर्स को देख रहा हूं। मुझे देखने के लिए सबसे नज़दीकी रोक रद्द कर दी गई थी, लेकिन फिर मुझे फिर से फंक्शन के साथ टाइमर को फिर से बनाना होगा। क्या मैं कुछ भुल गया?
ericslaw

आपको गलत रास्ते पर ले जाने के लिए क्षमा करें। मैंने अपने उत्तर से उस अशुद्धि को हटा दिया है।
बेन रॉबर्ट्स

1

मुझे स्लाइड शो जैसी सुविधा के लिए सेटटाइमआउट () को रोकने में सक्षम होना चाहिए।

यहाँ एक पॉज़ेबल टाइमर का अपना कार्यान्वयन है। यह टिम डाउन के उत्तर पर देखी गई टिप्पणियों को एकीकृत करता है, जैसे कि बेहतर ठहराव (कर्नेल की टिप्पणी) और प्रोटोटाइप का एक रूप (उमुर गेदिक की टिप्पणी)।

function Timer( callback, delay ) {

    /** Get access to this object by value **/
    var self = this;



    /********************* PROPERTIES *********************/
    this.delay = delay;
    this.callback = callback;
    this.starttime;// = ;
    this.timerID = null;


    /********************* METHODS *********************/

    /**
     * Pause
     */
    this.pause = function() {
        /** If the timer has already been paused, return **/
        if ( self.timerID == null ) {
            console.log( 'Timer has been paused already.' );
            return;
        }

        /** Pause the timer **/
        window.clearTimeout( self.timerID );
        self.timerID = null;    // this is how we keep track of the timer having beem cleared

        /** Calculate the new delay for when we'll resume **/
        self.delay = self.starttime + self.delay - new Date().getTime();
        console.log( 'Paused the timer. Time left:', self.delay );
    }


    /**
     * Resume
     */
    this.resume = function() {
        self.starttime = new Date().getTime();
        self.timerID = window.setTimeout( self.callback, self.delay );
        console.log( 'Resuming the timer. Time left:', self.delay );
    }


    /********************* CONSTRUCTOR METHOD *********************/

    /**
     * Private constructor
     * Not a language construct.
     * Mind var to keep the function private and () to execute it right away.
     */
    var __construct = function() {
        self.starttime = new Date().getTime();
        self.timerID = window.setTimeout( self.callback, self.delay )
    }();    /* END __construct */

}   /* END Timer */

उदाहरण:

var timer = new Timer( function(){ console.log( 'hey! this is a timer!' ); }, 10000 );
timer.pause();

कोड का परीक्षण करने के लिए, का उपयोग करें timer.resume()औरtimer.pause() कुछ समय और जाँच कितना समय बचा है। (सुनिश्चित करें कि आपका कंसोल खुला है।)

सेटटाइमआउट () के स्थान पर इस ऑब्जेक्ट का उपयोग करना उतना ही आसान है जितना कि इसके स्थान timerID = setTimeout( mycallback, 1000)पर timer = new Timer( mycallback, 1000 )। तब timer.pause()और आपके timer.resume()लिए उपलब्ध हैं।



0

टॉप रेटेड उत्तर के आधार पर टाइपस्क्रिप्ट कार्यान्वयन

/** Represents the `setTimeout` with an ability to perform pause/resume actions */
export class Timer {
    private _start: Date;
    private _remaining: number;
    private _durationTimeoutId?: NodeJS.Timeout;
    private _callback: (...args: any[]) => void;
    private _done = false;
    get done () {
        return this._done;
    }

    constructor(callback: (...args: any[]) => void, ms = 0) {
        this._callback = () => {
            callback();
            this._done = true;
        };
        this._remaining = ms;
        this.resume();
    }

    /** pauses the timer */
    pause(): Timer {
        if (this._durationTimeoutId && !this._done) {
            this._clearTimeoutRef();
            this._remaining -= new Date().getTime() - this._start.getTime();
        }
        return this;
    }

    /** resumes the timer */
    resume(): Timer {
        if (!this._durationTimeoutId && !this._done) {
            this._start = new Date;
            this._durationTimeoutId = setTimeout(this._callback, this._remaining);
        }
        return this;
    }

    /** 
     * clears the timeout and marks it as done. 
     * 
     * After called, the timeout will not resume
     */
    clearTimeout() {
        this._clearTimeoutRef();
        this._done = true;
    }

    private _clearTimeoutRef() {
        if (this._durationTimeoutId) {
            clearTimeout(this._durationTimeoutId);
            this._durationTimeoutId = undefined;
        }
    }

}

0

सर्वर साइड पर सेटटाइमआउट पॉज़ेबल बनाने के लिए आप नीचे की तरह कर सकते हैं (Node.js)

const PauseableTimeout = function(callback, delay) {
    var timerId, start, remaining = delay;

    this.pause = function() {
        global.clearTimeout(timerId);
        remaining -= Date.now() - start;
    };

    this.resume = function() {
        start = Date.now();
        global.clearTimeout(timerId);
        timerId = global.setTimeout(callback, remaining);
    };

    this.resume();
};

और आप इसे नीचे की तरह देख सकते हैं

var timer = new PauseableTimeout(function() {
    console.log("Done!");
}, 3000);
setTimeout(()=>{
    timer.pause();
    console.log("setTimeout paused");
},1000);

setTimeout(()=>{
    console.log("setTimeout time complete");
},3000)

setTimeout(()=>{
    timer.resume();
    console.log("setTimeout resume again");
},5000)


-1

यदि आपके पास छिपाने के लिए कई divs हैं, तो आप ऐसा करने के लिए एक setIntervalऔर कई चक्रों का उपयोग कर सकते हैं :

<div id="div1">1</div><div id="div2">2</div>
<div id="div3">3</div><div id="div4">4</div>
<script>
    function hideDiv(elm){
        var interval,
            unit = 1000,
            cycle = 5,
            hide = function(){
                interval = setInterval(function(){
                    if(--cycle === 0){
                        elm.style.display = 'none';
                        clearInterval(interval);
                    }
                    elm.setAttribute('data-cycle', cycle);
                    elm.innerHTML += '*';
                }, unit);
            };
        elm.onmouseover = function(){
            clearInterval(interval);
        };
        elm.onmouseout = function(){
            hide();
        };
        hide();
    }
    function hideDivs(ids){
        var id;
        while(id = ids.pop()){
            hideDiv(document.getElementById(id));
        }
    }
    hideDivs(['div1','div2','div3','div4']);
</script>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.