How to stop asynchronous function in JavaScript? -


i have asynchronous problems. i'm working on ecmascript 6 object. it's timer , want able restart during countdown.

here work:

export class timer {     constructor(sec){         this.sec = sec;         this.count = sec;         this.running = false;     }      start() {         this.running = true;         this._run();     }      _run(){         if(this.running){             settimeout(()=>{                 this.count --;                 console.log(this.count);                 if(this.count<0){                     this.running = false;                 }                 this._run();             }, 1000);         }     }      restart(){         this.running = false;         /*             wait until _run() done :         */         this.count = this.sec;         this.start();     } } 

in restart() function, how can know when _run() has stopped running?

an easier way know if timer "running" perhaps use setinterval instead.

var interval = setinterval(() => updatetimer(), 10); // update every 10ms 

it's running if interval set

if (interval) // timer running 

stop timer

window.clearinterval(interval); interval = null; // timer no longer "running" 

additional notes

beware of creating timers increment fixed value

in code, have

settimeout(() => this.count--, 1000); 

the intention decrement count property once every second, not behavior guaranteed.

check out little script

var state = {now: date.now()};  function delta(now) {   let delta = - state.now;   state.now = now;   return delta; }  setinterval(() => console.log(delta(date.now())), 1000);  // output 1002 1000 1004 1002 1002 1001 1002 1000 

we used setinterval(fn, 1000) actual interval varies couple milliseconds each time.

the problem exaggerated if things switch browser's focus different tab, open new tab, etc. @ these more sporadic numbers

1005 // close 1000 ms 1005 // ... 1004 // little variance here 1004 // ... 1834 // switched focus previous browser tab 1231 // let timer tab run in background couple seconds 1082 // ... 1330 // ... 1240 // ... 2014 // switched timer tab 1044 // switched previous tab 2461 // rapidly switched many tabs below 1998 // ... 2000 // @ these numbers... 1992 // not close 1000 ms set interval 2021 // ... 1989 // switched tab 1040 // ... 1003 // numbers appear stabilize while tab in focus 1004 // ... 1005 // ... 

so, means can't rely upon settimeout (or setinterval) function getting run once per 1000 ms. count decremented variance depending on wide variety of factors.

to work around this, need use delta. means before each "tick" of timer, need take timestamp using date.now. on next tick, take new timestamp , subtract previous timestamp new one. delta. using value, add timer's total ms precise number of milliseconds timer has been running for.

then, time-sensitive values projection/calculation of total accumulated ms.

in case, have count starts @ 10. if want count down -1 each 1000 ms, do

function update() {   // update totalms   this.totalms += calculatedelta();   // display count based on totalms   console.log("count %d", math.ceil(this.count - this.totalms/1000)); } 

here's sample es6 timer implements delta function might you

class timer {   constructor(resolution=1000, ms=0) {     this.ms = ms     this.resolution = resolution;     this.interval = null;   }   delta(now) {     let delta = - this.now;     this.now = now;     return delta;   }   start() {     this.now = date.now();     this.interval = window.setinterval(() => this.update(), this.resolution);   }   reset() {     this.update();     this.ms = 0;   }   stop() {     this.update();     window.clearinterval(this.interval);     this.interval = null;   }   update() {     this.ms += this.delta(date.now());     console.log("%d ms - %0.2f sec", this.ms, this.ms/1000);   } } 

create new timer 50 ms "resolution". means timer display updated every 50 ms. set value , timer still keep accurate value.

var t = new timer(50); t.start(); 

to simulate reset, can create one-off timeout can see reset working

// in ~5 seconds, reset timer once settimeout(() => t.reset(), 5000); 

here's demonstration of pausing timer

// in ~10 seconds, pause timer settimeout(() => t.stop(), 10000); 

and can resume timer, too

// in ~12 seconds, resume timer (without reset) settimeout(() => t.start(), 12000); 

you can start, stop, reset timer as like


here's es6 (above) transpiled es5 can see code working in runnable snippet. open console , click run code snippet.

"use strict";    function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call class function"); } }    var timer = (function () {    function timer() {      var resolution = arguments.length <= 0 || arguments[0] === undefined ? 1000 : arguments[0];      var ms = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];        _classcallcheck(this, timer);        this.ms = ms;      this.resolution = resolution;      this.interval = null;    }      timer.prototype.delta = function delta(now) {      var delta = - this.now;      this.now = now;      return delta;    };      timer.prototype.start = function start() {      var _this = this;        this.now = date.now();      this.interval = window.setinterval(function () {        return _this.update();      }, this.resolution);    };      timer.prototype.reset = function reset() {      this.update();      this.ms = 0;    };      timer.prototype.stop = function stop() {      this.update();      window.clearinterval(this.interval);      this.interval = null;    };      timer.prototype.update = function update() {      this.ms += this.delta(date.now());      console.log("%d ms - %0.2f sec", this.ms, this.ms / 1000);    };      return timer;  })();    var t = new timer(50);  t.start();    // in ~5 seconds, reset timer once  settimeout(function () {    return t.reset();  }, 5000);    // in ~10 seconds, pause timer  settimeout(function () {    return t.stop();  }, 10000);    // in ~12 seconds, resume timer (without reset)  settimeout(function () {    return t.start();  }, 12000);


Comments