setTimeout的核心原理和巧用
你所不了解的setTimeout
小编推荐:掘金是一个高质量的技术社区,从 ECMAScript 6 到 Vue.js,性能优化到开源类库,让你不错过前端开发的每一个技术干货。各大应用市场搜索「掘金」即可下载APP,技术干货尽在掌握..
看到了一篇不错的文章《你会用setTimeout吗 》,转载过来的,改了个名字,一下子感觉搞大上了,嘎嘎。
加了几个关于 setTimeout 和setInterval的小知识:
关于setInterval()和setTimeout()返回值
setInterval(),setTimeout() 会返回一个值,一般认为是ID,将这个ID值传递给clearInterval(),clearTimeout() 可以取消执行,例如:
js 代码:
- var intervalTimer=setInterval(function(){
- console.log(1)
- },3000);
- console.log(intervalTimer); //一般是一个数字,Number
- button.onclick=function(){
- clearInterval(intervalTimer);
- };
关于setInterval()和setTimeout()中回调函数中的this
setInterval(),setTimeout() 方法是浏览器 window
对象提供,所以第一个参数函数中的this
指向window
对象,这跟变量的作用域有关:
js 代码:
var a=1;
- var obj={
- a:2,
- b:function(){
- setTimeout(function(){
- console.log(this.a);//这里返回的是:1;
- },2000);
- }
- };
- obj.b();
当然你可以通过使用bind()方法来改变这个情况:
js 代码:
- var a=1;
- var obj={
- a:2,
- b:function(){
- setTimeout(function(){
- console.log(this.a);//这里返回的是:2;
- }.bind(this),2000);//注意这行
- }
- };
- obj.b();
关于bind()方法,你可以看这里:http://www.css88.com/archives/5611
关于setInterval()和setTimeout()的参数
大家都知道setInterval()和setTimeout()可以接收两个参数,第一个参数是需要回调的函数,必须传入的参数,第二个参数是时间间隔,毫秒数,可以省略,这个可以看文章的下面,
不传第二个参数,浏览器自动配置时间,在IE,FireFox中,第一次配可能给个很大的数字,100ms上下,往后会缩小到最小时间间隔,Safari,chrome,opera则多为10ms上下。
但是我要说的当然不是这个,我要说的是setInterval()和setTimeout()可以接收更多的参数,那么这些参数是干什么用的呢?从第三个参数开始,依次用来表示第一个参数(回调函数)传入的参数,例如:
js 代码:
- setTimeout(function(a,b){
- console.log(1+a+b);//这里打印的是:8
- },1000,3,4);
当然一些古老的浏览器是不支持的。
关于clearInterval()和clearTimeout()
clearInterval()和clearTimeout()其实是通用的,就是说你可以用 clearInterval() 取消 setTimeout() 执行,clearTimeout()同样可以取消 setInterval() 执行。
js 代码:
- var intervalTimer=setInterval(function(){
- console.log(1)
- },3000);
- console.log(intervalTimer);
- button.onclick=function(){
- clearTimeout(intervalTimer); //注意这里,不是clearInterval哦
- };
=============== 以下内容来源: 你会用setTimeout吗 ===================
教科书里面的setTimeout
定义很简单
setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。
广泛应用场景
定时器,轮播图,动画效果,自动滚动等等
上面一些应该是setTimeout在大家心中的样子,因为我们平常使用也不是很多。
但是setTimeout真的有那么简单吗?
测试题
一个题目,如果你在一段代码中发现下面内容
js 代码:
- var startTime = new Date();
- setTimeout(function () {
- console.log(new Date() - startTime);
- }, 100)
请问最后打印的是多少?
我觉得正确答案是,取决于后面同步执行的js需要占用多少时间。MIN(同步执行的时间, 100)
。
再加一个题目,只有下面代码
js 代码:
- setTimeout(function () {
- func1();
- }, 0)
- func2();
func1和func2谁会先执行?
这个答案应该比较简单,func2先执行,func1后面执行。
再来一题
js 代码:
- setTimeout(function () {
- func1()
- }, 0)
js 代码:
- setTimeout(function () {
- func1()
- })
有什么差别?
0秒延迟,此回调将会放到一个能立即执行的时段进行触发。javascript代码大体上是自顶向下的,但中间穿插着有关DOM渲染,事件回应等异步代码,他们将组成一个队列,零秒延迟将会实现插队操作。
不写第二个参数,浏览器自动配置时间,在IE,FireFox中,第一次配可能给个很大的数字,100ms上下,往后会缩小到最小时间间隔,Safari,chrome,opera则多为10ms上下。
上面答案来自《javascript框架设计》
好了,看了上面几个题目是不是感觉setTimeout不是想象中那样了。
setTimeout和单线程
下面是我自己的一些理解
首先需要注意javascript是单线程的,特点就是容易出现阻塞。如果一段程序处理时间很长,很容易导致整个页面hold住。什么交互都处理不了怎么办?
简化复杂度?复杂逻辑后端处理?html5的多线程?
上面都是ok的做法,但是setTimeout也是处理这种问题的一把好手。
setTimeout一个很关键的用法就是分片,如果一段程序过大,我们可以拆分成若干细小的块。
例如上面的情况,我们将那一段复杂的逻辑拆分处理,分片塞入队列。这样即使在复杂程序没有处理完时,我们操作页面,也是能得到即使响应的。其实就是将交互插入到了复杂程序中执行。
换一种思路,上面就是利用setTimeout实现一种伪多线程的概念。
有个函数库Concurrent.Thread.js
就是实现js的多线程的。
一个简单使用的例子,引入Concurrent.Thread.js
后
js 代码:
- Concurrent.Thread.create(function(){
- for (var i = 0;i<1000000;i++) {
- console.log(i);
- };
- });
- $('#test').click(function () {
- alert(1);
- });
虽然有个巨大的循环,但是这时不妨碍你去触发alert();
是不是很厉害~
还有一种场景,当我们需要渲染一个很复杂的DOM时,例如table组件,复杂的构图等等,假如整个过程需要3s,我们是等待完全处理完成在呈现,还是使用一个setTimeout分片,将内容一片一片的断续呈现。
其实setTimeout给了我们很多优化交互的空间。
如何使用
setTimeout这么厉害,那么我们是需要在在项目中大量使用吗?
我这边的观点是非常不建议,在我们业务中,基本上是禁止在业务逻辑中使用setTimeout的,因为我所看到的很多使用方式都是一些问题不好解决,setTimeout作为一个hack的方式。
例如,当一个实例还没有初始化的前,我们就使用这个实例,错误的解决办法是使用实例时加个setTimeout,确保实例先初始化。
为什么错误?这里其实就是使用hack的手段
第一是埋下了坑,打乱模块的生命周期
第二是出现问题时,setTimeout其实是很难调试的。
我认为正确的使用方式是,看看生命周期(可参考《关于软件的生命周期 》),把实例化提到使用前执行。
综上,setTimeout其实想用好还是很困难的, 他更多的出现是在框架和类库中,例如一些实现Promis的框架,就用上了setTimeout去实现异步。
所以假如你想去阅读一些源码,想去造一些轮子,setTimeout还是必不可少的工具。
setTimeout的核心原理和巧用的更多相关文章
- 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现
本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...
- docker核心原理
容器概念. docker是一种容器,应用沙箱机制实现虚拟化.能在一台宿主机里面独立多个虚拟环境,互不影响.在这个容器里面可以运行着我饿们的业务,输入输出.可以和宿主机交互. 使用方法. 拉取镜像 do ...
- HDFS 核心原理
HDFS 核心原理 2016-01-11 杜亦舒 HDFS(Hadoop Distribute File System)是一个分布式文件系统文件系统是操作系统提供的磁盘空间管理服务,只需要我们指定把文 ...
- 剖析SSH核心原理(一)
在我前面的文章中,也试图总结过SSH,见 http://blog.csdn.net/shan9liang/article/details/8803989 ,随着知识的积累,总感觉以前说得比较笼统, ...
- 关于Ajax的技术组成与核心原理
1.Ajax 特点: 局部刷新.提高用户的体验度,数据从服务器商加载 2.AJax的技术组成 不是新技术,而是之前技术的整合 Ajax: Asynchronous Javascript And Xml ...
- javascript真的是异步的吗?且看setTimeout的实现原理以及setTimeout(0)的使用场景
在今天之前我一直以为setTimeout这个函数是异步的,无意中看到了一篇关于setTimeout的文章.发现自己曾经的认识全是错误的,赶紧总结下. 先看一段代码: var start = new D ...
- Libevent核心原理
Libevent 是一个事件驱动框架, 不能仅说他是一个网络库. notejs就是采用与libevent类似的libev来做核心驱动的. Libevent支持三种事件:io事件.信号事件.时间事件 ...
- 高性能消息队列 CKafka 核心原理介绍(上)
欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:闫燕飞 1.背景 Ckafka是基础架构部开发的高性能.高可用消息中间件,其主要用于消息传输.网站活动追踪.运营监控.日志聚合.流式 ...
- Python面向对象篇之元类,附Django Model核心原理
关于元类,我写过一篇,如果你只是了解元类,看下面这一篇就足够了. Python面向对象之类的方法和属性 本篇是深度解剖,如果你觉得元类用不到,呵呵,那是因为你不了解Django. 在Python中有一 ...
随机推荐
- AtrousConvolution和dilated convolution
唉,真烦哪些炒概念的,把整个世界都给弄乱了. 这里说一下dilated convolution和atrous convolution. 这两种是一样的,至少keras源码中是一样的.在keras中调用 ...
- vim 使用、设置笔记
一.设置.vimrc( windows下通常为_vimrc) 1.设置vim中tab的缩进 set ts=4 (注:ts是tabstop的缩写,设TAB宽4个空格) set expandtab (注 ...
- [HNOI 2010] 弹飞绵羊
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2002 [算法] LCT动态维护森林连通性 时间复杂度 : O(NlogN ^ 2) ...
- npm 引入第三方过滤器
根据项目具体情况使用过滤器,如果不满足业务需求可以在vue的全局或者局部自定义fiter(过滤器) 一下是github提供的第三方过滤器: https://github.com/freearhey/v ...
- .NETFramework:StaticValueInjecter
ylbtech-.NETFramework:StaticValueInjecter 1.程序集 Omu.ValueInjecter, Version=3.1.1.0, Culture=neutral, ...
- htop 详细功能使用简介
一.htop 简介 This is htop, an interactive process viewer for Linux. It is a text-mode application (for ...
- 3.sql中的向上递归和向下递归
1.向下递归 select * from table_name where 条件 connect by prior bmbm(本级关联条件)=sjbmbm(上级关联条件) start with bmb ...
- HTML学习笔记(二)HTML格式化
很多标签都可以用来改变文本的外观,并为文本关联其隐藏的含义.总地来说,这些标签可以分成两类:基于内容的样式(content-based style)和物理样式(physical style). 一.基 ...
- PhpStorm之配置数据库连接
打开编辑器,找到编辑器右侧的 Database 点击 Database,点击左上角的 + ,选择Data Source ,再点击需要连接的数据库类型(因为我的数据库是MySQL,所以使用MySQL数据 ...
- hihocoder #1607 : H星人社交网络(双指针)
传送门 题意 分析 可知对与某个数x,设其可发送信息的边界为[L,R],那么随着x的递增,[L,R]也右移,故可对输入数排序,做一次双指针即可 trick 代码 //1. Aj < 1/8 * ...