简体   繁体   English

javascript中如何在一个时间间隔内做一个任务

[英]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?在 JavaScript 里面,我怎么知道在某个时间段内要做什么? For example, for 5 seconds, the value of a variable will increase and it will stop after 5 seconds.比如5秒,一个变量的值会增加,5秒后它会停止。 Of course, there are setinterval and settimeout, but they only do that work after that period of time is over.当然,也有 setinterval 和 settimeout,但它们只在那个时间段结束后才起作用。 I want that work to be done during that time.我希望在那段时间完成这项工作。

setInterval设置间隔

You can use setInteveral , but it's mostly trash for everything I've ever attempted to use it for.您可以使用setInteveral ,但对于我曾经尝试使用它的所有内容来说,它基本上都是垃圾。 In the code below, the counter will only increment to around 35 in 1 second;在下面的代码中,计数器只会在 1 秒内增加到 35 左右; about 28 milliseconds per interval -每个间隔大约28 毫秒-

 // 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 .更合适的实用程序是setImmediate It is supported in Node but not in browsers yet.它在 Node 中受支持,但在浏览器中尚不支持。 Polyfills are available if you plan to use this in the browser.如果您打算在浏览器中使用 Polyfills,则可以使用它。

async generators异步生成器

Above we see setInterval is quite slow.上面我们看到setInterval非常慢。 Another approach is to use an asynchronous generator.另一种方法是使用异步生成器。 In the code below, the counter can reach over 300,000 in just 1 second;在下面的代码中,计数器可以在 1 秒内达到 300,000 以上; About 3.3 microseconds per interval.每个间隔大约3.3 微秒

 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 .如果目标是在固定持续时间内尽可能快地运行该过程,我们将跳过昂贵的操作,如document.write In the example below the counter can reach over 1M in just 1 second;在下面的示例中,计数器可以在 1 秒内达到 1M 以上; just under 1 microsecond per interval -每个间隔不到1 微秒-

 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阻塞while循环

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.如果循环本身程序的主要部分,并且您只想在固定的时间内尽可能快地运行计数器,请使用while循环。 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"

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.如果时间已经过去,您将需要检查某种循环内部,确保循环本质上是异步的,否则 JS 主线程会出现问题。

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->我从这里修改了 PI 计算器Javascript: PI (π) Calculator to run for 5 seconds 而不是无限,它使用 requestAnimationFrame 来保持异步->

 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>

 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM