1

I want to auto increment a counter after click without blocking the interactions with the browser. I know that I need setTimeout or setInterval , but don't know how to implement. Any help will be appreciated.
Here is the code

HTML

<button id="start">start</button>

JavaScript

let start= document.querySelector('#start'); 

const counter = () => {
  for(let i = 0; i<1000; i++){
  console.log(i)
 }
}

start.addEventListener("click", counter);
Greg
  • 255
  • 2
  • 8
  • 19

2 Answers2

2

Set a Promise and await till the runtime.

const start = document.getElementById("start");
const bar = document.getElementById("bar");
const percent = document.getElementById("percent");
const results = document.getElementById("results");

let promisseId = 0;

const counter = (n = 100) => {
  if (n > 100) {
    n = 100;
  }

  promisseId++;

  return new Promise((resolve) => {
    // Here you can set a reject, (resolve, reject) the reject() must run in case your counter throws an error...
    const id = promisseId;

    let i = 1; // i is set outsite.
    const interval = setInterval(function() {
      if (i === n) {
        clearInterval(interval);
        resolve({
          i,
          id
        });
      }
      bar.value = i++;
    }, 100);
  });
};

start.addEventListener(
  "click",
  () =>
    counter(parseInt(this.percent.value)).then((res) => {
    const p = document.createElement("p");
    p.innerText = `Promise ${res.id} resolved! It goes to ${res.i}%`;
    results.appendChild(p);
  })
); // console.log the "res" when its resolved! You can use another value instead of 100 at counter(100).
<input id="bar" type="range" min="1" max="100" value="1" /> Go to <input id="percent" type="number" value="100" />% |
<button id="start">Start</button>
<p>Run it multiple times and simultaneously w/ different values, to see the magic!</p>
<div id="results"></div>

On the above example try Starting an 100% execution and imediatly an 10%, you will see the execution of 10% ending before the full one.

Just to make it complete, this will be a case using both, resolve and reject:

new Promise((resolve, reject) => {
  if (yourCondition) {
    resolve('Something to return as Success');
  } else {
    reject('Something to return on Failed');
  }
});
Iago Calazans
  • 329
  • 1
  • 10
  • @ Iago Calazans thank you very much for answer. Your answer is what I want and very smart. But I could't run it. gives " Uncaught SyntaxError: Unexpected token '{' ". Can you take a look, please? – Greg Sep 08 '20 at 19:50
  • Hey @Greg, i made it! Sorry for this little mistake! – Iago Calazans Sep 08 '20 at 19:54
  • Hey @Iago Calazans , thank you for quick response. I did it, now it doesn't throw any error, but there is no output in console. – Greg Sep 08 '20 at 19:59
  • now code runs but in the end throws this error "Uncaught (in promise) ReferenceError: i is not defined" – Greg Sep 08 '20 at 20:11
  • let i must be set outsite the for to be enable outsite it. The For function in JS have it own scope! :) – Iago Calazans Sep 08 '20 at 20:22
  • Did you make it work? – Iago Calazans Sep 09 '20 at 12:29
  • 1
    Hey @Iago Calazans unfortunately not. it is not asynchronous and doesn't work on click button, check here https://codesandbox.io/s/wonderful-cdn-ro439?file=/src/assignment-1.js:525-559 – Greg Sep 09 '20 at 13:43
  • Oh ok! On the eventListener i was calling it directly instead of using it as a callback! I fixed it, check it! It need to be () => counter() .... – Iago Calazans Sep 09 '20 at 13:50
  • Hey @Iago Calazans button works, but it is still not asynchronous , check here https://codesandbox.io/s/wonderful-cdn-ro439?file=/src/index.js:602-629 – Greg Sep 09 '20 at 14:18
  • @Greg i've made a few changes on your code to show you it at works! The value you pass on counter() call will be the range slide trough. – Iago Calazans Sep 09 '20 at 14:59
  • If you click on "Start" multiple times you will see it working Asyc! :) – Iago Calazans Sep 09 '20 at 15:16
  • Hey @Iago Calazans, thank you, now it works:). Have a great day – Greg Sep 10 '20 at 09:05
  • Thanks! I think my answer is more complete then the other one on your question! hahaha – Iago Calazans Sep 10 '20 at 13:02
1

const output = document.getElementById("output");
 
function start() {
  let counter = 0;
  setInterval(() => {
    output.innerHTML = ++counter;
  }, 1000);
}
<div id="output">0<div>
<button onclick="start()">Start</button>
sidthesloth
  • 1,399
  • 1
  • 11
  • 19