网站首页 > 技术文章 正文
前言
如果写过js代码的人对于setTimeout方法一定不会感到陌生。setTimeout是一种定时器,在前端开发中有很多的应用场景,比如在购物车结算成功后,等待几秒会自动跳转至列表页。今天我们就深入的看下setTimeout的实现原理。
Javascript之setTimeout
基本用法
根据W3C的标准解释,setTimeout是定义一个在指定时间后触发的函数。
我们先来看看setTimeout的基本用法,实现这样一个简单的效果,点击一个button,在3秒后页面上的文字消失。
setTimeout基本用法
由于这段代码非常基础,这里不做过多讲述。
setTimeout(fn, 0)
上面一部分说到setTimeout是相当于给函数定义一个‘闹钟’,当到了指定的时间后就会自动执行函数。但是如果我们将时间设置为0,即出现setTimeout(fn, 0)这样的代码,情况是怎么样的呢?是会立即执行吗?
我们可以通过以下一段代码来进行测试。
测试代码
如果和我们猜测的一样,立即执行的话,上面的测试代码会按照1 > 2 > 3的顺序输出,但是实际运行后,我们发现输出结果的顺序为1 > 3 > 2,而且不管运行多少次结果都不变。
出现了这样的结果,就证明了setTimeout(0)并不是立即执行的,那这又该怎么解释呢?
JS单线程执行
为了解释上面这个问题,我们要追溯到JS执行过程,我们都知道JS是单线程执行,所有的异步事件,包括自定义的页面DOM事件,定时器,Ajax请求都会被添加到一个任务列表按照顺序执行。
因为JS脚本文件是运行在浏览器端的,我们的JS引擎虽然是单线程的,但是对于浏览器来说确是多线程的。浏览器中不仅包括JS引擎,还包括网络请求Ajax,浏览器渲染等,它们都有特定的线程去执行。
setTimeout并不能作为多线程使用,可以通过以下一段代码来证明。
测试代码
对于以上一段代码,如果setTimeout可以作为多线程使用,则新的线程会在一秒后将isEnd属性设置false,那么在一秒后会alert出end字符串。
但是实际情况确是,页面从未打印出end字符串,而且页面会呈现锁死状态,这是因为isEnd变量值并未修改为false,相当于执行while(true),最终页面会崩溃。这也就能证明JS引擎是单线程执行状态。
事件队列
既然JS引擎是单线程执行,那么setTimeout定义的事件该具体何时触发呢?
这里我们需要深入到浏览器内核设计,在内核中涉及到一个事件队列的概念,我们可以直接看如下这张图。
事件队列
从上面这张图很容易看出,在浏览器内核中包含了各式各样的线程,有浏览器GUI渲染线程,Javascript引擎线程,网络请求线程。
在当JS引擎执行到其他线程相关的代码时,就会执行其他线程的代码,在其他线程执行完毕后需要JS引擎重新运行时,就会在JS引擎的事件队列里添加一个任务。
现在我们来看看setTimeout(0)做了什么?它会开启一个定时器线程,并不会影响后续的代码执行,这个定时器线程会在事件队列后面添加一个任务,例如上面图中的t3。等到前面的t1,t2执行完后再去执行t3,因此在前面第二部分内容中的输出顺序为1 > 3 > 2。
setInterval
既然说到了setTimeout,就不得不提到setInterval,setInterval同样作为一种定时器,是在指定的时间间隔后执行相应的函数。
一种最常见的场景是页面上的倒计时实现。这里我们实现一个简单的效果,指定一个时间,并进行倒计时。
倒计时
对比
setTimeout与setInterval虽然都是定时器,但是在执行上还是有不一样的。
setTimeout是指定的时间后执行一次;setInterval是在每隔指定的时间后执行多次。
setTimeout(fn1, t1),fn1的执行时间是大于或等于t1的;setInterval(fn2, t2),fn2的执行会始终尝试在t2时间后执行,如果网络请求较大的话,会出现fn2连续执行的情况。
总结
今天这篇文章主要讲解了Javascript中的setTimeout用法和执行原理,以及与setInterval的简单比较,大家学会了吗?
- 上一篇: 什么?你的 interval 定时器并不靠谱?
- 下一篇: 解决浏览器窗口切换后定时器执行异常的问题
猜你喜欢
- 2025-06-24 服务端性能测试实战3-性能测试脚本开发
- 2025-06-24 跨标签页通信(六):Cookie(cookie跨页面)
- 2025-06-24 崩溃!代码总掉链子?6 个 JavaScript 技巧助你稳操胜券
- 2025-06-24 如何取消一个已经开始的 JavaScript Promise
- 2025-06-24 Web页面如此耗电!到了某种程度,会是大损失
- 2025-06-24 setTimeout 出大 bug?为什么需要 setBigTimeout?
- 2025-06-24 悠然!午休十分钟分清 Vue 的 watch 和 computed,面试不发怵
- 2025-06-24 科普:CPU空闲时在忙什么?(cpu空闲温度)
- 2025-06-24 html5大神结合js带你研究古老读心术,你的心思早被猜透
- 2025-06-24 JWT + Refresh + SSO模版(jwt demo)
你 发表评论:
欢迎- 06-24发现一款开源宝藏级工作流低代码快速开发平台
- 06-24程序员危险了,这是一个 无代码平台+AI+code做项目的案例
- 06-24一款全新的工作流,低代码快速开发平台
- 06-24如何用好AI,改造自己的设计工作流?
- 06-24濮阳网站开发(濮阳网站建设)
- 06-24AI 如何重塑前端开发,我们该如何适应
- 06-24应届生靠这个Java简历模板拿下了5个offer
- 06-24服务端性能测试实战3-性能测试脚本开发
- 566℃Oracle分析函数之Lag和Lead()使用
- 565℃几个Oracle空值处理函数 oracle处理null值的函数
- 550℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 545℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 543℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 536℃【数据统计分析】详解Oracle分组函数之CUBE
- 526℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 519℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端富文本编辑器 (47)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle的函数 (57)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)