JavaScript is the language of the web. And it hasn't been the same since ES5 was released. More and more ideas and features are being ported from different languages and being integrated in JavaScript.
JavaScript是网络语言。 自从ES5发布以来,情况就不一样了。 越来越多的想法和功能正在从不同的语言移植并集成到JavaScript中。
One of those features are Promises, which are probably the most widely used feature in JavaScript after ES5 was released.
这些功能之一就是Promises,它可能是ES5发布后JavaScript中使用最广泛的功能。
But one of the things which JavaScript misses is a way to "pause" execution for a while and resume it later. In this post, I'll discuss how you can achieve that and what it really means to "pause" or "sleep" in JavaScript.
但是JavaScript遗漏的事情之一是一种“暂停”执行一段时间并在以后恢复执行的方法。 在本文中,我将讨论如何实现该目标以及在JavaScript中“暂停”或“睡眠”的真正含义。
Spoiler: JavaScript never really "pauses".
剧透:JavaScript从不真正地“暂停”。
TL; DR (TL;DR)
Here's the copy-pasta code which does the job:
这是完成任务的复制粘贴代码:
/**
*
* @param duration Enter duration in seconds
*/
function sleep(duration) {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, duration * 1000)
})
}
But what is really happening here?
但是,这里到底发生了什么?
setTimeout和伪承诺 (setTimeout and fake Promises)
Let's see a quick example using the above snippet (we'll discuss what's happening in it later):
让我们来看一个使用上述片段的简单示例(稍后我们将讨论其中发生的事情):
async function performBatchActions() {
// perform an API call
await performAPIRequest()
// sleep for 5 seconds
await sleep(5)
// perform an API call again
await performAPIRequest()
}
This function performBatchActions
, when called, simply executes the performAPIRequest
function, waits about 5 seconds, and then calls the same function again. Note how I wrote about 5 seconds, and not 5 seconds.
调用此函数performBatchActions
时,只需执行performAPIRequest
函数,等待约5秒钟 ,然后再次调用同一函数。 请注意我是如何写大约5秒而不是5秒的。
A strong note to put out there: the above code does not guarantee a perfect sleep. It means that if you specify duration to be, say, 1 second, JavaScript does not guarantee that it will start running the code after the sleep exactly after 1 second.
需要注意的是:以上代码不能保证完美的睡眠。 这意味着,如果将持续时间指定为1秒,则JavaScript 不能保证它将在睡眠后恰好1秒后开始运行代码。
Why not? you may ask. Unfortunately, it's because timers work in JavaScript, and in general, event loops. However, JavaScript absolutely guarantees that the piece of code after the sleep will never execute before the specified time.
为什么不? 你可能会问。 不幸的是,这是因为计时器在JavaScript中起作用,并且通常在事件循环中起作用。 但是,JavaScript绝对保证睡眠后的代码永远不会在指定时间之前执行。
So we don't really have a full indeterminate situation, just a partial one. And in most cases it's within a margin of a few milliseconds only.
因此,我们实际上并没有完全不确定的情况,只是部分情况。 而且在大多数情况下,仅在几毫秒的范围内。
JavaScript是单线程的 (JavaScript is single threaded)
A single thread means that a JavaScript process cannot really go out of the way at all. It has to do all the things - from event listeners, to HTTP callbacks, on the same main thread. And when one thing is executing, another one cannot execute.
单个线程意味着JavaScript进程根本不能完全脱离。 它必须在同一主线程上做所有事情-从事件侦听器到HTTP回调。 当一件事正在执行时,另一件事就无法执行。
Consider a webpage in which you have multiple buttons and you run the code above to simulate a sleep for, let's say, 10 seconds. What do you expect will happen?
考虑一个网页,其中有多个按钮,并运行上面的代码以模拟10秒钟的睡眠。 您期望会发生什么?
Nothing at all. Your webpage will work just fine, your buttons will be responsive, and once the 10 second sleep is done, the code next to it will execute. So it's evident that JavaScript does not really block the whole main thread because if it did that, your webpage would have frozen and the buttons would have become non-clickable.
没事 您的网页将正常运行,您的按钮将响应,并且在完成10秒钟的睡眠后,将执行其旁边的代码。 因此很明显,JavaScript并不会真正阻塞整个主线程,因为如果这样做,您的网页将被冻结并且按钮将变得不可单击。
So how did JavaScript actually pause a single thread, without ever really pausing it?
那么JavaScript如何真正暂停单个线程而又没有真正暂停它呢?
遇见活动循环 (Meet the Event Loop)
Unlike other languages, JavaScript doesn't just keep on executing code in a linear fashion from top to bottom. It is an asynchronous event-driven language with tons of magic in the form of the event loop.
与其他语言不同,JavaScript不仅保持从上到下以线性方式执行代码。 它是一种异步事件驱动语言,具有大量事件循环形式的魔力。
An event loop splits your code in synchronous and certain events - like timers and HTTP requests. Precisely speaking, there are two queues - a task queue and microtask queue.
事件循环将您的代码拆分为同步事件和某些事件,例如计时器和HTTP请求。 确切地说,有两个队列-任务队列和微任务队列。
Whenever you run JS, and there's an asynchronous thing (like a mouseclick event, or a promise), JavaScript throws it in the task queue (or microtask queue) and keeps executing. When it completes a "single tick", it checks if the task queues and microtask queue have some work for it. If yes, then it'll execute the callback/perform an action.
每当您运行JS时,都会发生异步事件(例如mouseclick事件或promise),JavaScript会将其扔到任务队列(或微任务队列)中并继续执行。 完成“单个滴答”之后,它将检查任务队列和微任务队列是否为此工作。 如果是,那么它将执行回调/执行一个动作。
I would really recommend anyone interested in the detailed workings of event loops to watch this video:
我真的建议任何对事件循环的详细工作感兴趣的人观看此视频:
结论 (Conclusion)
You came here for a simple sleep instruction in JavaScript, and ended up learning about one of the core things in JavaScript - event loops! Amazing, isn't it?
您是来这里用JavaScript编写简单的睡眠指令的,而最终了解了JavaScript的核心内容之一-事件循环! 太神奇了,不是吗?
Well, if you liked the article, checkout codedamn - a platform I've been building for developers and learners like you. Also, let's connect on social media - twitter and Instagram. See you soon!
好吧,如果您喜欢这篇文章,请查看codedamn-我一直在为像您这样的开发人员和学习者构建的平台。 另外,让我们连接社交媒体-twitter和Instagram 。 再见!
Peace
和平
翻译自: https://www.freecodecamp.org/news/javascript-sleep-wait-delay/