JSFiddle - React, Tailwind, and code Playground

HTML

<progress id="progressbar" value="0"></progress>
<span id="progressvalue"></span>
<br />
<span id="status"></span>
<br />
<button id="start_btn">старт</button>
<button id="stop_btn">стоп</button>

JavaScript

function Worker(opts) {
	var from = opts['from'] || 0;
  var to = opts['to'] || 100;
  var position = 0;
  var step = opts['step'];
  var interval = opts['interval'] || 500;
  var on_step = opts['on_step'] || function() {};
  var on_start = opts['on_start'] || function() {};
  var on_end = opts['on_end'] || function() {};
  var working = false;
  var timer;
  var self = this;
  
  //console.log(this);
  
  this.start = function() {
  	//console.log(interval);
  	if (working) return;
  
  	position = 0;
  	timer = window.setInterval(function() {
    	//console.log('timer');
    	position += step;
      on_step(position, from, to);
      if (position >= to) {
      	console.log('end1');
      	self.stop();
      }
    }, interval);
    on_start();
    working = true;
    on_step(position, from, to);
  };
  
  this.stop = function() {
  	console.log('end2');
  	if (!working) return;
    
    //console.log(timer);
    window.clearInterval(timer);
    working = false;
    on_end();
  };
  
  this.is_working = function() {
  	return working;
  }
}



var worker;

$(document).ready(function() {
	
	worker = new Worker({
  	from: 0,
    to: 100,
    step: 5,
    interval: 300,
    on_step: function(pos, from, to) {
    	//console.log(pos, from, to);
    	$('#progressbar').attr('max', to - from).attr('value', pos);
      $('#progressvalue').text(Math.round(pos / (to - from) * 100) + '%');
    },
    on_start: function() {
    	$('#status').text('работаем...');
    },
   	on_end: function() {
    	$('#status').text('закончили!');
    },
  });
  
  //console.log(worker);
  //worker.start();
  
  $('#start_btn').click(function() {
  	worker.start();
  });
  
  $('#stop_btn').click(function() {
  	worker.stop();
  });
});