用故事解析setTimeout和setInterval(内含js单线程和任务队列)
区别:
setTimeout(fn,t):
延迟调用,超过了时间就调用回调函数,返回一个id,使用clearTimeout(id)取消执行。
注意:取消了里面的回调函数就不执行了哦,而不是取消的时候就立即执行,下面有源码可以自己cv试一下。
setInterval(fn,t):
循环调用,有周期性的调用回调函数,返回一个id,使用clearInterval(id)取消执行。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<script>
console.log('333333333333333333333')
var aa =setTimeout(()=>{
console.log("11111111111111")
},6000)
setTimeout(()=>{
clearTimeout(aa)
console.log("2222222222")
},3000)
</script>
</head>
<body>
</body>
</html>
在学习这两种延迟函数之前要最好是先了解一下JS单线程和任务队列;
举个栗子:
在广场上,只有一家一点点奶茶店(cpu),然后我(一个任务)要去买奶茶(执行这个任务),只能排一条队(js的单线程机制),虽说排队(主线程)的人很多,但是一点点工作人员工作速度确实很快,一般的人付完现金就完了(synchronous同步任务)。
但是到了我的时候,我想用支付宝支付,但是打开支付宝需要网络,需要等待支付宝软件打开(asynchronous异步任务,等待IO设备返回结果),但是为了不影响队列后面的排队者的速度,所以一点点的工作人员让我去旁边的队列里(任务队列)去等待,这个队列里面有加我一起有三个人在启动支付宝,我排在第三。
然后一段时间过后,我的和第一个人支付宝打开了(IO设备返回结果了),第二个人没打开,我和第一个人就把二维码展示出来(在任务队列中添加一个事件,表示相关异步任务可以进入主线程执行了),但是这个时候主队列里面还有一些人在买奶茶,所以,现在工作人员顾不上我。
然后我们就只能一直等待,直到主队列里面买奶茶的人都走光了,这个时候工作人员就把我和第一个人加入主队列中,然后我和第一个人就相继都买到奶茶了,主队列又没有人了,于是工作人员又去问第二个人二维码有没有出来,(这个过程叫Event Loop(事件循环)),至此基本的单线程和任务队列就完了,下面再了解一下定时器的特殊原理。
setTimeout(fn,t)
同样的,又是我(setTimeout(fn,20)函数)去买奶茶,我首先还是去排队,到我的时候我说我现在不想买,我要等到20(设置的时长)毫秒之后再买,工作人员就说,好,那你去任务队列里面去等20毫秒吧,然后我就屁颠屁颠的去了。
20毫秒后,还是老样子,工作人员要等到主队列里面人都走完了再把我拉到主队列里面去,所以我实际等待的时间=我设置的时间+设置时间到了之后主队列里面执行的时间,但是庆幸的是工作人员工作速度非常快,所以一般主队列里面是没有人的。
注意:
1、所以即使你设置超时时间为0,工作人员也不会立马执行你哦,还是会把你加到任务队列中的,谁叫你是asynchronous(异步任务)
2、你设置超时时间有用吗?实际上是没有生效的,因为html5标准规定了setTimeout设置超时时间最小值是4毫秒,如果低于这个值就会自动增加,老版本浏览器更将是把最短时间设为10毫秒,而最要命的是,如果涉及到DOM的变动的都是16毫秒一次。
setInterval(fu,t)
同样的,鸣人(setInterval(fn,1000)函数)去买奶茶,首先还是去排队,到鸣人的时候,它不仅要在1秒钟之后买,还要影分身出很多鸣人相继在1、2、3、4...之后买,工作人员同样要他和他的影分身在任务队列后面排队等会,正常情况下,主队列没人了,鸣人和他的影分身们也会在规定的时间里面相继执行。
那么问题来了
假如每个鸣人都很喜欢逼逼叨叨,那么就会发生这样子的情况:
当一秒钟后第一个鸣人从任务队列中到主队列中的时候,就一直跟工作人员逼逼叨叨(发生阻塞了,例如遇到循环不完的for),直到第四秒钟才说完(也就是b了3秒钟),这个时候第二个鸣人已经超过预定时间的两秒钟了,然后等到第二个鸣人和工作人员聊得时候又逼逼叨叨不停,又要b3秒钟,所以第二个鸣人会在第7秒b完,同理,第三个和第四个分别在第10秒和第13秒b完。
鸣人逼逼叨叨的过程如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>uaoie.top</title>
<script>
console.log('333333333333333333333')
var y=0;
var x = new Date().getTime();
var d=setInterval(a,1000);
function a() {
y++;
sleep(3000);
if(y>=4){
clearInterval(d)
}
console.log(new Date().getTime()-x);
}
function sleep(sleepTime){
var start=new Date().getTime();
while(true){
if(new Date().getTime()-start>sleepTime){
break;
}
}
}
</script>
</head>
<body>
</body>
</html>
导致的情况如下:
全剧终
八、彩蛋
现在我们可以很轻松的分析一下下面代码的原理(虽然我们都知道结果):
var aa=new Date().getTime()
for (var i = 0; i < 4; i++) {
setTimeout(function() {
console.log(new Date().getTime() -aa, i);
}, 1000);
}
console.log(new Date().getTime() -aa, i);
先执行第一行,完了后执行for,循环4次也就是执行4次setTimeout函数,这个4个函数同时放在任务队列中。
然后再执行最下面的config,所以会先打印0秒和4。
然后等到一秒后,setTimeout函数从任务队列中出来到主队列,输出的是1秒和4。
所以效果如下:
用故事解析setTimeout和setInterval(内含js单线程和任务队列)的更多相关文章
- 关于js中的setTimeout和setInterval
http://ejohn.org/blog/how-javascript-timers-work 这是John的一篇博文说到setTimeout和setInterval的区别,在看js高效图形编程的时 ...
- js:setTimeout 与 setInterval 比较
在javascript中有两个非常有用的函数:setTimeout 和setInterval ,都是定时器:但是两者存在着一些区别: 1. setTimeout函数 用法:setTimeout(fn, ...
- js点击按钮倒计时setTimeout和setInterval
setTimeout() 用于在指定的毫秒数后调用函数或计算表达式,只执行 code 一次. setInterval() 可按照指定的周期(以毫秒计)来调用函数或计算表达式,不停地调用函数,直到 cl ...
- 原生js轮播以及setTimeout和setInterval的理解
下面这个代码是从一个群下载下来的,为了帮助自己理解和学习现在贴出来,与初学者共勉. <!DOCTYPE html> <html> <head> <meta c ...
- js setTimeout 与 setInterval 以及 for 循环 刷新UI
1. setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式:执行一次: 如果需要执行多次,自身再次调用 setTimeout(): 示例:无穷循环并带停止按钮的 <html&g ...
- js里的setTimeout和setInterval之后的页面是空白,阻塞浏览器的document对象,但是不阻塞script方法
js里的setTimeout和setInterval是否进程阻塞? 阻塞浏览器的document对象,但是不阻塞script方法 当你在setTimeout中使用document.write时是不行的 ...
- js中的setTimeout和setInterval
在html页面中要使用自动刷新功能时,可以是使用js中setTimeout和setInterval: 一.使用方法 setTimeout的使用setTimeout('要调用的Js方法', 调用的延迟时 ...
- js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)
javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...
- 【转】JS中setTimeout和setInterval的最大延时值详解
前言 JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成.而这篇文中主要给大家介绍的是关于JS中setTi ...
随机推荐
- Oracle 数据库登录、用户解锁、改密码、创建用户授权操作
一.数据库登录1.常用账户: 管理员: sys主要练习操作用户: scott2.测试环境是否配置成功: 1.命令窗口 win+R -> cmd(以管理员身份运行) - > sqlplus ...
- Unity3D热更新之LuaFramework篇[09]--资源热更新与代码热更新的具体实现
前言 在上一篇文章 Unity3D热更新之LuaFramework篇[08]--热更新原理及热更服务器搭建 中,我介绍了热更新的基本原理,并且着手搭建一台服务器. 本篇就做一个实战练习,真正的来实现热 ...
- 警惕!CAF效应导致PCB漏电
最近碰到一个PCB漏电的问题,起因是一款低功耗产品,本来整机uA级别的电流,常温老化使用了一段时间后发现其功耗上升,个别样机功耗甚至达到了mA级别.仔细排除了元器件问题,最终发现了一个5V电压点,在产 ...
- 小伙子,你真的清楚 JVM GC ?
序 正文 如何确定垃圾? 前面已经提到 JVM 可以采用 引用计数法 与 可达性分析算法 来确定需要回收的垃圾,我们来具体看一下这两种算法: 引用计数法 该方法实现为:给每个对象添加一个引用计数器,每 ...
- 神奇的 SQL 之子查询,细节满满 !
前言 开心一刻 有一天,麻雀遇见一只乌鸦. 麻雀问:你是啥子鸟哟 ? 乌鸦说:我是凤凰. 麻雀说:哪有你龟儿子这么黢黑的凤凰 ? 乌鸦说:你懂个铲铲,老子是烧锅炉的凤凰. 子查询 讲子查询之前,我们先 ...
- 编码规范 | Java函数优雅之道(上)
导读 随着软件项目代码的日积月累,系统维护成本变得越来越高,是所有软件团队面临的共同问题.持续地优化代码,提高代码的质量,是提升系统生命力的有效手段之一.软件系统思维有句话“Less coding, ...
- Android使用com.google.android.cameraview.CameraView进行拍照
import android.Manifest;import android.annotation.SuppressLint;import android.content.Context;import ...
- 牛客多校训练第八场C.CDMA(思维+构造)
题目传送门 题意: 输入整数m( m∈2k ∣ k=1,2,⋯,10),构造一个由1和-1组成的m×m矩阵,要求对于任意两个不同的行的内积为0. 题解: Code: #include<bits/ ...
- red hat enterprise Linux 64 bit 配置IP
在win7 64位操作系统的台式机器上,安装了VMware® Workstation,9.0.1 build-894247.新建一个虚拟机安装linux.具体过程请搜索相关文档.安装的时候选择的网络连 ...
- Spring Boot 支持 Https 有那么难吗?
https 现在已经越来越普及了,特别是做一些小程序或者公众号开发的时候,https 基本上都是刚需了. 不过一个 https 证书还是挺费钱的,个人开发者可以在各个云服务提供商那里申请一个免费的证书 ...