Home > OS >  Stopwatch in TS returns NaN
Stopwatch in TS returns NaN

Time:01-27

I have a Stopwatch that has two problems.

In the code, there is a class with several methods, the currentWatch class is supposed to return a time (milliseconds, seconds, minutes).

  1. The first is that there is a millisecond NaN and I don't know how to fix it.
  2. And the second I want when I click the start (after the stop) from the continuation of that.

typescript code :

class StopWatch {
   private duration: number;
   private status: string;
   private currentTime: any;
   private domRef: HTMLElement | null;
   private interval: any;
   private milliSecond: number;
   private second:number;
   private minute: number;

   constructor(wrapper: string) {
      this.duration = 0;
      this.milliSecond = 0;
      this.second = 0;
      this.minute = 0;

      this.domRef = document.getElementById(wrapper);
      this.status = 'stopped';
      
      if (!this.domRef) throw new Error('Does not exist');
      this.render();
   }

   private render() {
         this.domRef!.append(
            createBtn('start', () => this.start()),
            createBtn('stop', () => this.stop()),
            createBtn('reset', () => this.reset()),
         )
   }

   private start() {
      if(this.status === 'started') throw new Error('already started');
      this.currentTime = Date.now();
      this.status = 'started';

      const p = document.createElement("p");
      p.id = "p";
      document.body.appendChild(p);

      this.interval =  setInterval(() => {
         this.minute, this.second, this.milliSecond  = Number(this.currentWatch());
         document.getElementById("p")!.innerHTML =  `${this.minute} : ${this.second} : ${this.milliSecond}`;
      }, 100);
   }

   private currentWatch() {
      this.duration = Date.now() - this.currentTime;

      if(this.status === 'stopped') this.stop();

      let minutes = Math.floor(this.duration / (1000 * 60));
      let seconds = Math.floor((this.duration % (1000 * 60)) / 1000);
      let milliSeconds = Math.floor(this.duration % 1000);

      this.minute = minutes;
      this.second = seconds;
      this.milliSecond = milliSeconds;
      
      return [this.minute, this.second, this.milliSecond];
   }

   stop() {
      clearInterval(this.interval);
      if(this.status === 'stopped') throw new Error('already stopped');

      this.duration = Date.now() - this.currentTime   this.duration;

      this.status = 'stopped';

      return this.duration;
   }

   reset(){
      if(this.status === 'started') this.stop();
      this.duration = 0;
      document.getElementById("p")!.innerHTML = this.duration.toString();
   }
}

function createBtn(name: string, listener: () => void) {
   const startBtn = document.createElement('button');
   startBtn.innerText = name;
   startBtn.addEventListener('click', listener);
   return startBtn;
}

(function() {
   const btns = document.getElementsByClassName('add-btn');
   btns[0].addEventListener('click', () => {
      new StopWatch(btns[0].getAttribute('data-idw') as string);
   });
})();

I put the compiled code of TypeScript to show the result.

var StopWatch = /** @class */ (function () {
    function StopWatch(wrapper) {
        this.duration = 0;
        this.milliSecond = 0;
        this.second = 0;
        this.minute = 0;
        this.domRef = document.getElementById(wrapper);
        this.status = 'stopped';
        if (!this.domRef)
            throw new Error('Does not exist');
        this.render();
    }
    StopWatch.prototype.render = function () {
        var _this = this;
        this.domRef.append(createBtn('start', function () { return _this.start(); }), createBtn('stop', function () { return _this.stop(); }), createBtn('reset', function () { return _this.reset(); }));
    };
    StopWatch.prototype.start = function () {
        var _this = this;
        if (this.status === 'started')
            throw new Error('already started');
        this.currentTime = Date.now();
        this.status = 'started';
        var p = document.createElement("p");
        p.id = "p";
        document.body.appendChild(p);
        this.interval = setInterval(function () {
            _this.minute, _this.second, _this.milliSecond = Number(_this.currentWatch());
            document.getElementById("p").innerHTML = "".concat(_this.minute, " : ").concat(_this.second, " : ").concat(_this.milliSecond);
        }, 100);
    };
    StopWatch.prototype.currentWatch = function () {
        this.duration = Date.now() - this.currentTime;
        if (this.status === 'stopped')
            this.stop();
        var minutes = Math.floor(this.duration / (1000 * 60));
        var seconds = Math.floor((this.duration % (1000 * 60)) / 1000);
        var milliSeconds = Math.floor(this.duration % 1000);
        this.minute = minutes;
        this.second = seconds;
        this.milliSecond = milliSeconds;
        return [this.minute, this.second, this.milliSecond];
    };
    StopWatch.prototype.stop = function () {
        clearInterval(this.interval);
        if (this.status === 'stopped')
            throw new Error('already stopped');
        this.duration = Date.now() - this.currentTime   this.duration;
        this.status = 'stopped';
        return this.duration;
    };
    StopWatch.prototype.reset = function () {
        if (this.status === 'started')
            this.stop();
        this.duration = 0;
        document.getElementById("p").innerHTML = this.duration.toString();
    };
    return StopWatch;
}());
function createBtn(name, listener) {
    var startBtn = document.createElement('button');
    startBtn.innerText = name;
    startBtn.addEventListener('click', listener);
    return startBtn;
}
(function () {
    var btns = document.getElementsByClassName('add-btn');
    btns[0].addEventListener('click', function () {
        new StopWatch(btns[0].getAttribute('data-idw'));
    });
})();
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>StopWatch</title>
</head>
<body>
   <button  data-idw="qwe">Add new StopWatch</button>
   <div id="qwe"></div>
   <script src="main.js"></script>
</body>
</html>

CodePudding user response:

It looks like your currentWatch function is returning an array.

In your start function, you create a new Number with the value returned from currentWatch.

Number accepts only a single input.

Perhaps, refactor your start method to something like this

      this.interval =  setInterval(() => {
         this.currentWatch();
         document.getElementById("p")!.innerHTML =  `${this.minute} : ${this.second} : ${this.milliSecond}`;
      }, 100);

CodePudding user response:

You have to set the variables from the array in start like this:

[_this.minute, _this.second, _this.milliSecond] = _this.currentWatch();

Since currentWatch() returns an array.

Of course there are also other ways to do that, but this one might be closest to your original code.

  • Related