How to do a task in a time interval in javascript

inside JavaScript, how can I tell something to be done in a certain period of time? For example, for 5 seconds, the value of a variable will increase and it will stop after 5 seconds. Of course, there are setinterval and settimeout, but they only do that work after that period of time is over. I want that work to be done during that time.

Upvotes: 1

Views: 679

Answers (3)

Mulan
Mulan

Reputation: 135406

setInterval

You can use setInteveral, but it's mostly trash for everything I've ever attempted to use it for. In the code below, the counter will only increment to around 35 in 1 second; about 28 milliseconds per interval -

// initialize a counter
let counter = 0

// increment the counter on interval
let myprocess = setInterval(_ => counter++, 0)

// after 5 seconds, stop the process and log the counter value
setTimeout(_ => { clearInterval(myprocess); console.log(counter) }, 1000)

A more appropriate utility would be setImmediate. It is supported in Node but not in browsers yet. Polyfills are available if you plan to use this in the browser.

async generators

Above we see setInterval is quite slow. Another approach is to use an asynchronous generator. In the code below, the counter can reach over 300,000 in just 1 second; About 3.3 microseconds per interval.

async function *count(until) {
  let counter = 0
  while (Date.now() < until) {
    yield counter++
  }
}

async function main() {
  for await (const n of count(Date.now() + 1000))
    document.write(`${n}, `)
  return "done"
}

main().then(console.log)

If the goal is to run the process as fast as possible for the fixed duration, we will skip expensive operations like document.write. In the example below the counter can reach over 1M in just 1 second; just under 1 microsecond per interval -

async function *count(until) {
  let counter = 0
  while (Date.now() < until) {
    yield counter++
  }
}

async function run(process, duration) {
  let result
  for await (const n of process(Date.now() + duration))
    result = n
  return result
}

run(count, 1000).then(console.log)
// 1045592

blocking while loop

If the loop itself is the main part of your program and you want simply want to run the counter as fast as possible for a fixed duration, use a while loop. Note this will block all other code from running for the entire duration of the loop -

function count(until) {
  let n = 0
  while (Date.now() < until)
    n++
  return n
}

setTimeout(console.log, 0, "I was blocked")

console.log(count(Date.now() + 1000))

// 36618673
// "I was blocked"

Upvotes: 2

kennarddh
kennarddh

Reputation: 2665

const setRunInSeconds = (callback, ms = 1000, delay = 1) => {
  const intervalId = setInterval(callback, delay)

  setInterval(() => {
    clearInterval(intervalId)
  }, ms)
}

let num = 0

setRunInSeconds(() => {
  console.log('interval: ' + num)

  num += 1
}, 5000, 1)

Upvotes: 1

Keith
Keith

Reputation: 24231

You will need to check inside some sort of loop if the time has passed, make sure the loop is async in nature or the JS main thread will have issues.

I have modified PI calculator from here Javascript: PI (π) Calculator to run for 5 seconds instead of infinite , it's using requestAnimationFrame to keep things async->

function * generateDigitsOfPi() {
    let q = 1n;
    let r = 180n;
    let t = 60n;
    let i = 2n;
    while (true) {
        let digit = ((i * 27n - 12n) * q + r * 5n) / (t * 5n);
        yield Number(digit);
        let u = i * 3n;
        u = (u + 1n) * 3n * (u + 2n);
        r = u * 10n * (q * (i * 5n - 2n) + r - t * digit);
        q *= 10n * i * (i++ * 2n - 1n);
        t *= u;
    }
}

// Demo
let iter = generateDigitsOfPi();

const tmStart = Date.now();//

let output = document.querySelector("div");
(function displayNextDigit() {
    output.insertAdjacentHTML("beforeend", iter.next().value);
    scrollTo(0, document.body.scrollHeight);
  if (Date.now() - tmStart < 5000) requestAnimationFrame(displayNextDigit);
})();
div { word-wrap:break-word; font-family: monospace }
<div></div>

Upvotes: 1

Related Questions