当前位置:首页 > 科技  > 软件

JavaScript怎么模拟 delay、sleep、pause、wait 方法

来源: 责编: 时间:2023-09-22 20:12:28 232观看
导读许多编程语言都有一个 sleep 函数,可以延迟程序的执行若干秒。JavaScript缺少这个内置功能,但不用担心。在这篇文章中,我们将探讨在JavaScript代码中实现延迟的各种技巧,同时考虑到该语言的异步性质。如何在 JS 中创建 sl

许多编程语言都有一个 sleep 函数,可以延迟程序的执行若干秒。JavaScript缺少这个内置功能,但不用担心。在这篇文章中,我们将探讨在JavaScript代码中实现延迟的各种技巧,同时考虑到该语言的异步性质。YeV28资讯网——每日最新资讯28at.com

如何在 JS 中创建 sleep 函数

对于那些只想快速解决问题而不想深入了解技术细节的人,我们也有简单明了的解决方案。下面是如何在你的JavaScript工具箱中添加一个 sleep 函数的最直接方式:YeV28资讯网——每日最新资讯28at.com

function sleep(ms) {  return new Promise(resolve => setTimeout(resolve, ms));}console.log('Hello');sleep(2000).then(() => { console.log('World!'); });

运行这段代码,你会在控制台看到 “Hello”。然后,在短暂的两秒钟后,“World!”v会接着出现。这是一种既简洁又有效的引入延迟的方法。YeV28资讯网——每日最新资讯28at.com

如果你只是为了这个来的,那太好了!但如果你对“为什么”和“怎么做”的原因感到好奇,还有更多可以学习的内容。JavaScript中处理时间有其细微之处,了解这些可能会对你有所帮助。YeV28资讯网——每日最新资讯28at.com

理解JavaScript的执行模型

现在我们已经有了一个快速的解决方案,让我们深入了解JavaScript的执行模型的机制。理解这一点对于有效地管理代码中的时间和异步操作至关重要。YeV28资讯网——每日最新资讯28at.com

考虑以下Ruby代码:YeV28资讯网——每日最新资讯28at.com

require 'net/http'require 'json'url = 'https://api.github.com/users/jameshibbard'uri = URI(url)response = JSON.parse(Net::HTTP.get(uri))puts response['public_repos']puts 'Hello!'

正如人们所期望的,这段代码向GitHub API发送一个请求以获取我的用户数据。然后解析响应,输出与我的GitHub帐户关联的公共仓库的数量,最后在屏幕上打印“Hello!”。执行是从上到下进行的。YeV28资讯网——每日最新资讯28at.com

相比之下,这是相同功能的JavaScript版本:YeV28资讯网——每日最新资讯28at.com

fetch('https://api.github.com/users/jameshibbard')  .then(res => res.json())  .then(json => console.log(json.public_repos));console.log('Hello!');

如果你运行这段代码,它会先在屏幕上输出“Hello!”,然后输出与我的GitHub帐户关联的公共仓库的数量。YeV28资讯网——每日最新资讯28at.com

这是因为在JavaScript中,从API获取数据是一个异步操作。JavaScript解释器会遇到 fetch 命令并发送请求。然而,它不会等待请求完成。相反,它会继续执行,将“Hello!”输出到控制台,然后当请求在几百毫秒后返回时,它会输出仓库的数量。YeV28资讯网——每日最新资讯28at.com

如何在JavaScript中正确使用SetTimeout

既然我们已经更好地理解了JavaScript的执行模型,让我们看看JavaScript是如何处理延迟和异步代码的。YeV28资讯网——每日最新资讯28at.com

在JavaScript中创建延迟的标准方法是使用其 setTimeout 方法。例如:YeV28资讯网——每日最新资讯28at.com

console.log('Hello');setTimeout(() => {  console.log('World!'); }, 2000);

这将在控制台上输出 "Hello",然后两秒后输出 "World!"。在很多情况下,这已经足够了:做某事,然后在短暂的延迟后,做其他事情。问题解决!YeV28资讯网——每日最新资讯28at.com

但不幸的是,事情并不总是那么简单。YeV28资讯网——每日最新资讯28at.com

你可能会认为 setTimeout 会暂停整个程序,但事实并非如此。它是一个异步函数,这意味着其余的代码不会等待它完成。YeV28资讯网——每日最新资讯28at.com

例如,假设你运行了以下代码:YeV28资讯网——每日最新资讯28at.com

console.log('Hello');setTimeout(() => { console.log('World!'); }, 2000);console.log('Goodbye!');

你会看到以下输出:YeV28资讯网——每日最新资讯28at.com

HelloGoodbye!World!

注意“Goodbye!”是如何出现在“World!”之前的?这是因为 setTimeout 不会阻塞其余代码的执行。YeV28资讯网——每日最新资讯28at.com

这意味着你不能这样做:YeV28资讯网——每日最新资讯28at.com

console.log('Hello');setTimeout(1000);console.log('World');

"Hello" 和 "World" 会立即被记录在控制台上,之间没有明显的延迟。YeV28资讯网——每日最新资讯28at.com

你也不能这样做:YeV28资讯网——每日最新资讯28at.com

for (let i = 0; i < 5; i++) {  setTimeout(() => { console.log(i); }, i * 1000);}

花一秒钟考虑一下上面的代码片段可能会发生什么。YeV28资讯网——每日最新资讯28at.com

它不会在每个数字之间延迟一秒钟打印数字 0 到 4。相反,你实际上会得到五个 4,它们在四秒后一次性全部打印出来。为什么呢?因为循环不会暂停执行。它不会等待 setTimeout 完成才进入下一次迭代。YeV28资讯网——每日最新资讯28at.com

那么 setTimeout 实际上有什么用呢?现在让我们来看看。YeV28资讯网——每日最新资讯28at.com

setTimeout() 函数的检查和最佳实践

正如你可以在我们的 setTimeout 教程中阅读到的,原生JavaScript setTimeout 函数在指定的延迟(以毫秒为单位)后调用一个函数或执行一个代码片段。YeV28资讯网——每日最新资讯28at.com

这可能在某些情况下是有用的,例如,如果你希望在访问者浏览你的页面一段时间后显示一个弹出窗口,或者你希望在从元素上移除悬停效果之前有短暂的延迟(以防用户意外地鼠标移出)。YeV28资讯网——每日最新资讯28at.com

setTimeout 方法接受一个函数的引用作为第一个参数。YeV28资讯网——每日最新资讯28at.com

这可以是函数的名称:YeV28资讯网——每日最新资讯28at.com

function greet(){  alert('Howdy!');}setTimeout(greet, 2000);

它可以是一个指向函数的变量(函数表达式):YeV28资讯网——每日最新资讯28at.com

const greet = function(){  alert('Howdy!');};setTimeout(greet, 2000);

或者它可以是一个匿名函数(在这种情况下是箭头函数):YeV28资讯网——每日最新资讯28at.com

setTimeout(() => { alert('Howdy!'); }, 2000);

也可以将一段代码字符串传递给 setTimeout 以供其执行:YeV28资讯网——每日最新资讯28at.com

然而,这种方法是不可取的,因为:YeV28资讯网——每日最新资讯28at.com

  1. 它很难阅读(因此很难维护和/或调试)
  2. 它使用了一个隐含的 eval,这是一个潜在的安全风险
  3. 它比替代方案慢,因为它必须调用JS解释器

如前所述,setTimeout 非常适合在延迟后触发一次性操作,但也可以使用 setTimeout(或其表亲 setInterval)来让JavaScript等待直到满足某个条件。例如,下面是如何使用 setTimeout 等待某个元素出现在网页上的方式:YeV28资讯网——每日最新资讯28at.com

function pollDOM () {  const el = document.querySelector('my-element');  if (el.length) {    // Do something with el  } else {    setTimeout(pollDOM, 300); // try again in 300 milliseconds  }}pollDOM();

这假设该元素最终会出现。如果你不确定这是否会发生,你需要考虑取消计时器(使用 clearTimeout 或 clearInterval)。YeV28资讯网——每日最新资讯28at.com

在 JS 中使用递增超时作为 Sleep 函数的替代方案

有时,你可能会发现自己想要在一系列操作中引入延迟。虽然你可以使用各种方法来模拟一个Sleep函数,但还有另一种经常被忽视的方法:递增超时。YeV28资讯网——每日最新资讯28at.com

这个思路很简单:你不是暂停整个执行线程,而是使用 setTimeout 为每个后续操作增加延迟。这样,你可以创建一个延迟操作的序列,而不会阻塞浏览器或损害用户体验。YeV28资讯网——每日最新资讯28at.com

下面是一个快速示例:YeV28资讯网——每日最新资讯28at.com

let delay = 1000; // 从1秒的延迟开始for (let i = 0; i < 5; i++) {  setTimeout(() => {    console.log(`这是消息 ${i + 1}`);  }, delay);  delay += 1000; // 每次迭代延迟增加1秒}

在这个示例中,第一条消息将在1秒后出现,第二条消息在2秒后,依此类推,直到第五条消息在5秒后。YeV28资讯网——每日最新资讯28at.com

这种方法的优点是它不阻塞,易于实现,并且不需要了解 promises 或 async/await。然而,它不适用于需要精确计时或错误处理的复杂异步操作YeV28资讯网——每日最新资讯28at.com

现代JavaScript中的流控制

编写 JavaScript 时,我们经常需要等待某件事情发生(例如,从 API 获取数据),然后做出响应(例如,更新UI以显示数据)。YeV28资讯网——每日最新资讯28at.com

上面的示例使用了一个匿名回调函数来实现这一目的,但如果你需要等待多个事情发生,语法很快就会变得相当复杂,你最终会陷入回调地狱。YeV28资讯网——每日最新资讯28at.com

幸运的是,这门语言在过去几年里有了很大的发展,现在为我们提供了新的构造来避免这一点。YeV28资讯网——每日最新资讯28at.com

例如,使用 async await,我们可以重写最初获取 GitHub API信息的代码:YeV28资讯网——每日最新资讯28at.com

(async () => {  const res = await fetch(`https://api.github.com/users/jameshibbard`);  const json = await res.json();  console.log(json.public_repos);  console.log('Hello!');})();

现在,代码从上到下执行。JavaScript 解释器等待网络请求完成,首先记录公共仓库的数量,然后记录“Hello!”消息。YeV28资讯网——每日最新资讯28at.com

将Sleep函数引入原生JavaScript

如果你还在看这篇文章,那么我猜你一定是想阻塞那个执行线程,并让JavaScript等待一下。YeV28资讯网——每日最新资讯28at.com

下面是你可能会这样做的方式:YeV28资讯网——每日最新资讯28at.com

function sleep(milliseconds) {  const date = Date.now();  let currentDate = null;  do {    currentDate = Date.now();  } while (currentDate - date < milliseconds);}console.log('Hello');sleep(2000);console.log('World!');

正如预期的那样,这将在控制台上打印“Hello”,暂停两秒,然后打印“World!”YeV28资讯网——每日最新资讯28at.com

它通过使用Date.now方法获取自1970年1月1日以来经过的毫秒数,并将该值分配给一个 date 变量。然后它创建一个空的 currentDate 变量,然后进入一个 do ... while 循环。在循环中,它会重复获取自1970年1月1日以来经过的毫秒数,并将该值分配给之前声明的 currentDate 变量。只要 date 和 currentDate 之间的差异小于所需的毫秒数的延迟,循环就会继续进行。YeV28资讯网——每日最新资讯28at.com

任务完成了,对吗?好吧,也不完全是……YeV28资讯网——每日最新资讯28at.com

如何在JavaScript中编写更好的Sleep函数

也许这段代码正是你所期望的,但请注意,它有一个很大的缺点:循环会阻塞JavaScript的执行线程,并确保在它完成之前没有人能与你的程序进行交互。如果你需要很大的延迟,甚至有可能会让整个程序崩溃。YeV28资讯网——每日最新资讯28at.com

那么应该怎么做呢?YeV28资讯网——每日最新资讯28at.com

事实上,也可以结合本文前面学到的技巧来制作一个不太侵入性的 sleep 方法:YeV28资讯网——每日最新资讯28at.com

function sleep(ms) {  return new Promise(resolve => setTimeout(resolve, ms));}console.log('Hello');sleep(2000).then(() => { console.log('World!'); });

这段代码将在控制台上打印“Hello”,等待两秒,然后打印“World!”在底层,我们使用setTimeout 方法在给定的毫秒数后解析一个 promise。YeV28资讯网——每日最新资讯28at.com

注意,我们需要使用一个 then 回调来确保第二条消息是带有延迟的。我们还可以在第一个回调函数后面链式地添加更多回调函数。YeV28资讯网——每日最新资讯28at.com

这样做是可行的,但看起来不太好看。我们可以使用async ... await来美化它:YeV28资讯网——每日最新资讯28at.com

function sleep(ms) {  return new Promise(resolve => setTimeout(resolve, ms));}async function delayedGreeting() {  console.log('Hello');  await sleep(2000);  console.log('World!');  await sleep(2000);  console.log('Goodbye!');}delayedGreeting();

这看起来更好看,但这意味着使用 sleep 函数的任何代码都需要被标记为 async。YeV28资讯网——每日最新资讯28at.com

当然,这两种方法仍然有一个缺点(或特点),那就是它们不会暂停整个程序的执行。只有你的函数会睡眠:YeV28资讯网——每日最新资讯28at.com

function sleep(ms) {  return new Promise(resolve => setTimeout(resolve, ms));}async function delayedGreeting() {  console.log('Hello');  await sleep(2000); // await只暂停当前的异步函数  console.log('World!');}delayedGreeting();console.log('Goodbye!');

上面的代码会依次打印出:YeV28资讯网——每日最新资讯28at.com

HelloGoodbye!World!

这样,你可以根据需要灵活地使用不同的方法和技术来实现JavaScript中的延迟和异步操作。YeV28资讯网——每日最新资讯28at.com

创建 JS Sleep函数的最佳实践

我们已经探讨了各种在JavaScript中引入延迟的方法。现在让我们总结一下哪种方法最适合不同的场景,以及哪种方法通常应该避免。YeV28资讯网——每日最新资讯28at.com

1.纯粹的setTimeout

console.log('Hello');setTimeout(() => { console.log('World!'); }, 2000);

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-11211-0.htmlJavaScript怎么模拟 delay、sleep、pause、wait 方法

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: C++ 中的隐式转换:机制、应用与警惕

下一篇: Spring常用注解@Import的三种使用方式,你都了解了吗?

标签:
  • 热门焦点
  • 5月iOS设备好评榜:iPhone 14仅排第43?

    5月iOS设备好评榜:iPhone 14仅排第43?

    来到新的一月,安兔兔的各个榜单又重新汇总了数据,像安卓阵营的榜单都有着比较大的变动,不过iOS由于设备的更新换代并没有那么快,所以相对来说变化并不大,特别是iOS好评榜,老款设
  • 容量越大越不坏?24万块硬盘故障率报告公布 这些产品零故障

    容量越大越不坏?24万块硬盘故障率报告公布 这些产品零故障

    8月5日消息,云存储服务商Backblaze发布了最新的硬盘故障率报告,年故障率有所上升。Backblaze发布的硬盘季度统计数据,其中包括故障率等重要方面。这些结
  • K6:面向开发人员的现代负载测试工具

    K6:面向开发人员的现代负载测试工具

    K6 是一个开源负载测试工具,可以轻松编写、运行和分析性能测试。它建立在 Go 和 JavaScript 之上,它被设计为功能强大、可扩展且易于使用。k6 可用于测试各种应用程序,包括 Web
  • 一年经验在二线城市面试后端的经验分享

    一年经验在二线城市面试后端的经验分享

    忠告这篇文章只适合2年内工作经验、甚至没有工作经验的朋友阅读。如果你是2年以上工作经验,请果断划走,对你没啥帮助~主人公这篇文章内容来自 「升职加薪」星球星友 的投稿,坐
  • JavaScript学习 -AES加密算法

    JavaScript学习 -AES加密算法

    引言在当今数字化时代,前端应用程序扮演着重要角色,用户的敏感数据经常在前端进行加密和解密操作。然而,这样的操作在网络传输和存储中可能会受到恶意攻击的威胁。为了确保数据
  • 一文搞定Java NIO,以及各种奇葩流

    一文搞定Java NIO,以及各种奇葩流

    大家好,我是哪吒。很多朋友问我,如何才能学好IO流,对各种流的概念,云里雾里的,不求甚解。用到的时候,现百度,功能虽然实现了,但是为什么用这个?不知道。更别说效率问题了~下次再遇到,
  • 慕岩炮轰抖音,百合网今何在?

    慕岩炮轰抖音,百合网今何在?

    来源:价值研究所 作者:Hernanderz&ldquo;难道就因为自己的一个产品牛逼了,从客服到总裁,都不愿意正视自己产品和运营上的问题,选择逃避了吗?&rdquo;这一番话,出自百合网联合创
  • 机构称Q2国内智能手机销量同比下滑4% vivo份额重回第1

    机构称Q2国内智能手机销量同比下滑4% vivo份额重回第1

    7月29日消息,根据市场调查机构Counterpoint Research公布的最新报告,2023年第2季度中国智能手机销量同比下降4%,创新自2014年以来第2季度销量新低。报
  • 超闭合精工铰链 彻底消灭缝隙 三星Galaxy Z Flip5与Galaxy Z Fold5发布

    超闭合精工铰链 彻底消灭缝隙 三星Galaxy Z Flip5与Galaxy Z Fold5发布

    2023年7月26日,三星电子正式发布了Galaxy Z Flip5与Galaxy Z Fold5。三星新一代折叠屏手机采用超闭合精工铰链,让折叠后的缝隙不再可见。同时,配合处
Top
Baidu
map