以前做小白时,只知道setTimeout是延时器,可以让代码延迟执行,当今天被IOS13的禁止在程序主线程以外修改布局,被虐哭。
是一个用框架写的APP,里面用了一个时间选择器,需要在渲染选择器外层样式之后,再重新渲染时间选项。那么问题来了,怎么办0.0 检查了时间插件之后,发现并没有什么问题。所以就默默加了setTimeout(),突然发现,好了。。。
下面是当时测试在控制台的报错。。。
Modifications to the layout engine must not be performed from a background thread
解决完问题之后,决定去看看真正的setTimeout到底是什么样的,路过一位大佬的博客,感觉大佬讲解的很明白,作为笔记记下来保留一份,以便日后查阅。
感谢大佬的详细讲解,大佬链接镇楼。
下面就是正文啦
大佬的例子是一个景点的JavaScript题
for(var i=1; i<=9; i++) {
setTimeout(function(){
console.log( i );
},1000 );
}
答案呢,是9个10,为什么咩?
其实原理是因为,我们在for循环中定义的变量i,在for循环结束后并没有走出它的作用域,循环一次,定时器就会加入任务队列,但是定时器并没有执行。也就是说for循环之后,i依然可以访问,值等于最后一次循环的值,循环了9次,就有了9次定时器。因此会输出9个10。
既然酱紫,那把上面的for语句稍微修改一下
for(var i=1; i<=9; i++) {
console.log( i );
setTimeout(function(){
console.log( i );
},1000 );
}
现在的答案你们猜到了么?
答案是1、2、3、4、5、6、7、8、9然后是9个10,解答同上。
可能这里最难理解的就是setTimeout的方式(注册事件):它有两个参数,第一个参数是函数,第二个参数是时间值。
调用setTimeout时,把函数参数放入事件队列中。等主程序运行完,再调用。
可以理解为1000ms之后,再放入事件队列中,如果此时队列为空,那么直接调用当前函数。如果前面还有其他时间,那就等待。
因此setTimeout是一个约会从来都不准时的小伙子
那现在代码再修改一下
for(var i=1; i<=9; i++) {
console.log( i );
setTimeout(function(){
console.log( i );
},1000 );
}
for(var i=0; i<3; i++) {
setTimeout(function(){
console.log( i );
},1000 );
console.log( i );
}
现在的答案咩:1、2、3、4、5、6、7、8、9、0、1、2,然后是3次3,然后是9次3,其他的不说了,至于为什么是先出现3次3,然后是9次3呢?其实是因为第二个参数即时间值不一样,所以先执行后一个时间戳。
注意:调用setTimeout时,把函数参数,放到事件队列中,等主程序运行完,再调用。即便是时间值为0,它也会等主程序执行完再执行,如果主程序队列为空,就会直接调用。
HTML5标准规定了setTimeout()的第二个参数的最小值(最短间隔),不得低于4毫秒,如果低于这个值,就会自动增加。老版本的浏览器都将最短间隔设为10毫秒。而这里设置为0,其实是想表达立即执行的意思,也就是说,等当前代码执行完(执行栈清空)以后,立即执行(0毫秒间隔)指定的回调函数。而实际上是最少4ms。
这是大佬写的setTimeout的详解,感觉看完明白了很多,完美。
最后是大佬的文章版权信息:
作者:江峰★
出处:http://www.cnblogs.com/jf-67/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利