【JavaScript基础】Js的定时器(你想看的原理也在哟)
【JavaScript基础】Js的定时器(你想看的原理也在哟)
博客说明
文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢!
说明
本章是经历第二次翻新,时过一年,再看自己的文章,觉得需要做点什么,它得丰富一点!篇幅半页或者一页,自己都感觉有点对不住自己。为了对得住自己,加了原理解析和案例。知其然与所以然。
Js的定时器,是前端的基本工具,在日常的开发和工作上也会经常的使用到。前端的定时器有两种,一种是一次性定时器,一种是重复性定时器。
一次性定时器setTimeout
标准:在指定的毫秒数后调用函数或计算表达式。
口语:使一段代码在指定时间后运行。
语法
setTimeout(code,millisec,lang)
| 参数 | 描述 |
|---|---|
| code | 必需。要调用的函数后要执行的 JavaScript 代码串。 |
| millisec | 必需。在执行代码前需等待的毫秒数。 |
| lang | 可选。脚本语言可以是:JScript | VBScript | JavaScript |
案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Js的定时器</title>
</head>
<body>
<p>点击按钮,在等待 3 秒后弹出 "Hello"。</p>
<button onclick="myFunction()">我是按钮,点我</button>
<script>
function myFunction() {
setTimeout(function () {
alert("Hello")
}, 1000 * 3);
}
</script>
</body>
</html>
重复性定时器setInterval
标准:按照指定的周期(以毫秒计)来调用函数或计算表达式。方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。
口语:可以使一段代码每过指定时间就运行一次。
语法
setInterval(code,millisec,lang)
| 参数 | 描述 |
|---|---|
| code | 必需。要调用的函数或要执行的代码串。 |
| millisec | 必须。周期性执行或调用 code 之间的时间间隔,以毫秒计。 |
| lang | 可选。 JScript | VBScript | JavaScript |
案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Js的定时器</title>
</head>
<body>
<input id="clock" />
<button onclick="clearDate()">别变了,快停止吧,点我!</button>
<script type="text/javascript">
const id = setInterval(() => {
const date = new Date();
const time = date.toLocaleTimeString();
document.getElementById("clock").value = time;
}, 1000);
function clearDate() {
clearInterval(id)
}
</script>
</body>
</html>
时间的误差
setInterval指定的是开始执行之间的间隔,并不考虑每次任务执行本身所消耗的时间。因此实际上,两次执行之间的间隔会小于指定的时间。
比如,setInterval指定每100ms执行一次,每次执行需要5ms,那么第一次执行结束后95毫秒,第二次执行就会开始。如果某次执行耗时特别长,比如需要105毫秒,那么它结束后,下一次执行就会立即开始。
为了确保两次执行之间有固定的间隔,可以不用setInterval,而是每次执行结束后,使用setTimeout指定下一次执行的具体时间。
var i = 1;
var timer = setTimeout(function() {
alert(i++);
timer = setTimeout(arguments.callee, 2000);
}, 2000);
消除定时器
在使用定时器的时候,需要有一个好的习惯,那就是清除定时器,特别是对于重复型定时器,一定要及时清除。
定时器清除的方法
相对于两种创建定时器的方法,Js也给出了相对应的清除方法,分别是clearTimeout(obj)和clearInterval(obj)。
在看到这两种方法都是接收一个参数,这个参数就是定时器的标识,这个标识在使用定时器的时候被定义用来接收定时器方法的变量。
案例
// 一秒之后打印
const test1 = setTimeout(function(){
console.log('hello world')
},1000);
// 每秒打印一次
const test2 = setInterval(function(){
console.log('hello world')
},1000)
// 清理定时器
clearTimeout(test1);
clearInterval(test2)
原理
JavaScript语言特性
JavaScript是一门基于对象的弱类型语言,它作为浏览器脚本语言,主要用途是负责与页面的交互,以及操作DOM。
重点来了,JavaScript的执行环境是单线程的,即默认情况下是同步加载的,也就是说 JavaScript的加载是阻塞的。在同一时间内JavaScript只能完成一件事,自上而下执行,下面的代码等待上面的代码解析完成。
在这种情况下,后面的代码其实就是被阻塞了。阻塞就意味着等待,等待就意味着用户体验,用户体验一来,那必须得使劲想办法,所以同步和异步出现了。
同步和异步
同步操作:队列执行。
异步操作:并线执行。
异步的任务不具有阻塞效应。
同步任务都是在主线程中执行,形成了一个执行栈,直到主线程空闲时,才会去事件队列中查看是否有可执行的异步任务,如果有就推入主进程中。
异步任务在JavaScript中是通过回调函数实现异步的,回到本文的主题,一旦使用了setTimeout(),里面的回调函数就是异步代码,但是这里面的代码不会立马执行,而是要等待主队列为空,并达到定的延时时间才会执行。
运行机制
setTimeout和setInterval的运行机制是,将指定的代码移出本次执行,等到下一轮Event Loop时,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就等到再下一轮Event Loop时重新判断。
这意味着,setTimeout和setInterval指定的代码,必须等到本轮Event Loop的所有同步任务都执行完,再等到本轮Event Loop的“任务队列”的所有任务执行完,才会开始执行。由于前面的任务到底需要多少时间执行完,是不确定的,所以没有办法保证在时间内执行。
案例
setTimeout(function() {
console.log("异步任务执行");
}, 0);
function a(x) {
console.log("a() 开始运行");
b(x);
console.log("a() 结束运行");
}
function b(y) {
console.log("b() 开始运行");
console.log(y);
console.log("b() 结束运行");
}
console.log("同步任务开始");
a("hello world");
console.log("同步任务结束");
// 同步任务开始
// a() 开始运行
// b() 开始运行
// hello world
// b() 结束运行
// a() 结束运行
// 同步任务结束
// 异步任务执行
总结
- JavaScript引擎是单线程,它会强制异步事件排队等待执行;
- setTimeout和setInterval执行原理是不一样的,需要注意他们的执行时间的影响;
- 如果一个一次性定时器(setTimeout)被阻塞了,它会等待直到有合适的执行时间(等待时间有可能比它定义的延迟时间长);
- 如果重复性定时器(setInterval)回调函数执行时间很长(长于定义的间隔时间)的话,间隔定时器有可能无间隔的持续执行。
感谢
万能的网络
公众号-归子莫,小程序-小归博客
【JavaScript基础】Js的定时器(你想看的原理也在哟)的更多相关文章
- Javascript 基础--JS函数(三)
一.基本概念:未完成某一个功能的代码(语句,指令)的集合. 二.函数的调用方式: 2.1.函数名(传递参数1,传递参数2) 基本语法 function 函数名(参数列表){ //代码; retur ...
- Javascript基础 - js中曾经忽略的知识点
深入那些曾经忽略的Javascript知识 1. parseInt(string, [radix]),parseFloat(string) 一般我们省略第二个参数,parseInt(‘100’) == ...
- javascript基础-js对象
一.js对象的创建 1.普通最简单的方式 var teacher = new Object( ); teacher.name = "zhangsan"; teacher.age = ...
- javascript基础-js继承
1.prototype方式 示例:没有使用prototype(下列这些代码只能获取array1数组的总和,而无法对array2数据进行求和) var array1 = new Array(1,4,9, ...
- JavaScript基础 -- js常用内置方法和对象
JS中常用的内置函数如下: 1.eval(str):计算表达式的结果. 2.parseInt(str,n):将符串转换成整数数字形式(可指定几进制). 3.parseFloat(str):将字符串转换 ...
- javascript基础-js函数
一.创建函数的方式 1)普通方式 function cal( num1, num2 ) { return num1+num2; } 2)使用变量初始化方式 var plus = function(nu ...
- JavaScript(JS)简介
历史背景介绍 (Brendan Eich)在其Netscape Navigator 2.0产品中开发出一套livescript的脚本语言.Sun和Netscape共同完成.后改名叫Javascript ...
- JavaScript——基础知识,开始我们的js编程之旅吧!
JavaScript基础第01天 1. 编程语言 编程语言: 可以通过类似于人类语言的"语言"来控制计算机,让计算机为我们做事情,这样的语言就叫做编程语言(Programming ...
- 【JavaScript】JS的坚实基础
前言 考虑到在后面的开发中,需要大量的使用js语言去进行开发,所以准备重新规整一下javascript的知识点,专门开了一个js的专栏,用来复习一下js语言.万事开头难,要是后面写的有问题的,欢迎 ...
随机推荐
- input竖直的输入框,文字从上到下排列
有的时候可能会有这样的需求,一个竖直的输入框,输入信息,文字也是从上到下排列: (但是在移动端或用轮播swiper时不起作用,可以用textarea代替input) <!DOCTYPE html ...
- git报错:Auto Merge Failed; Fix Conflicts and Then Commit
本文来源:http://blog.csdn.net/trochiluses/article/details/101007191.出错场景: 协同开发时,我们从远程服务器上pull下代码的时候,出现以下 ...
- 解决IE浏览器 点击子元素重复调用执行 mouseover 与mouseout兼容性问题
将函数配对换为下面2个就可以解决兼容性问题. mouseenter() mouseleave(0
- dedecms描述文字description长度截取办法
[field:description function='cn_substr(@me,126)' /]
- Shell系列(23)- 字符截取命令sed
简述 字符替换命令sed 和vi功能相似,但是vi是给用户用的,sed是给脚本用的 sed是一种几乎包括在所有的UNIX平台(包括Linux)的轻量级流编辑器.s sed主要是用来将数据进行选取.替换 ...
- 华为云计算IE面试笔记-FusionCompute虚拟机热迁移定义,应用场景,迁移要求,迁移过程
*热迁移传送了什么数据?保存在哪? 虚拟机的内存.虚拟机描述信息(配置和设备信息).虚拟机的状态 虚拟机的配置和设备信息:操作系统(类别.版本号).引导方式(VM通过硬盘.光盘.U盘.网络启动)和引导 ...
- P4606-[SDOI2018]战略游戏【圆方树,虚树】
正题 题目链接:https://www.luogu.com.cn/problem/P4606 题目大意 给出\(n\)个点\(m\)条边的一张图,\(q\)次询问给出一个点集,询问有多少个点割掉后可以 ...
- 微信小程序Canvas添加水印字体,通过setGlobalAlpha设置字体透明度。
微信小程序自带的设置透明度只有setGlobalAlpha,但是CanvasContext.setGlobalAlpha设置透明度,是全局透明,整张图片都透明了.所以直接使用是不行的. 换种思路实现: ...
- mysql8 主从搭建
主:192.168.10.2 从:192.168.10.3 主:1.登录mysql,授权账号,让从数据库可以进行复制. mysql CREATE USER 'repl'@'192.168.10.3' ...
- Xcode相关
Xcode相关的路径 Provisioning Profiles存放路径:~/Library/MobileDevice/Provisioning Profiles 所有模拟器(包括历史模拟器):~/L ...