We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
关于 setTimeout 的一些理解。
setTimeout
js不像java一样拥有sleep的功能,也就是将当前线程暂停一段时间后执行,因为js是基于事件机制工作的,所以它提供了 setTimeout 定时任务。
也就是说,如果你要实现一个sleep的功能,那也就只能将sleep后的任务,放到 setTimeout 的异步回调函数中执行吧!
本文就简单介绍一下 setTimeout 的原理,以及实际工作中的作用。
为什么js要搞成单线程?而不像java一样可以并发呢?根源在于js前期是嵌套在浏览器中的,而浏览器是直接跟用户打交道,对于人看到的结果而言,如果一次性并行执行多个任务,人!是会凌乱的。
当然,随着 node.js 的出现,js多线程不是梦,因为它的出现让大家知道:js不止能跑在浏览器上,还可以用在服务器端。所以,只要在服务器端,那么多线程的事情,终究会解决。虽然现在 node.js 全程异步机制已经很高效了!
node.js
为什么这么说呢?其实对于js而言,所以的任务,全部都进入队列,只不过它将当前执行的任务,叫做 主任务,而在 主任务 中产生的附加的动作全部进入 任务队列 ,当主线程执行完后,按照 FIFO 的原则,依次执行 任务队列 中的任务。
主任务
任务队列
FIFO
其实整个事件处理过程 = Main Task + Event Loop[**注意:**loop其实是个while(true),一直无线循环]
setTimeout 的作用,就是改变上面 任务队列 中任务的执行顺序的,上文提到,队列中的任务是 FIFO(先进先出) 的。但是!!!如果你给这个任务增加延迟时间,那么情况就不一样啦。
也就是说上文提到的 Event Loop ,如果其中各任务都是立即执行的,那么按顺序来,如果有延迟,那么你就靠后一点吧。
Event Loop
有了上面解释,大家看看两个例子:
示例1:
setTimeout(function(){ console.log('等待2秒执行') },2000); console.log('立即执行');
结果:
立即执行 等待2秒执行
解释:
在执行这几行代码时,主任务(Main Task)上只有一行语句:
console.log('立即执行');
而开始出现的代码,由于设置了延迟,所以进入任务队列(Event Loop):
setTimeout(function(){ console.log('等待2秒执行') },2000);
所以,按照执行顺序 Main Task -> Event Loop,结果也就顺理成章了。
Main Task -> Event Loop
示例2:
setTimeout(function(){ console.log('等待2秒执行') },2000); while(true){ console.log('立即执行'); };
console.log('立即执行'); console.log('立即执行'); ...
由于 Main Task 是一个死循环,一直执行不完,所以 Event Loop中的任务,就没有机会被执行了。
Main Task
为什么要把延迟时间设置为0,单独拿出来说呢?因为这个在实际开发中,很有意义的!
setTimeout的一个作用,就是让其中执行的任务,脱离当前主任务,延后执行,所以 setTimeout(fn,0) 的一个作用,就是改变当前任务的执行顺序。
setTimeout(fn,0)
比如上面的 示例1,就是活生生的例子。
示例1
那么,好奇的你又可能要问题了,好生生的我为什么要改变顺序呢?如果要改,我把2个的顺序提前就调转一下就好了嘛,为什么还要 setTimeout 呢,多此一举。
你说的太对了, setTimeout(fn,0) 就是解决这个场景的,即:不能改变事件发生的顺序,而又希望事件按需要的顺序发生。
示例:
我们都知道,js的2个特征:事件捕获 和 事件冒泡。
事件捕获
事件冒泡
我们就用 事件捕获 来打个比方:
document.onclick = function(){ console.log('document click!'); }; document.getElementById('myEle').onclick = function(){ console.log('element click!'); };
element click! document click!
当你点击页面上的 #myEle元素的时候,必然会最后触发 'document click!',因为 事件冒泡。
#myEle
'document click!'
这时候,如果你希望 document.onclick 先执行,因为这里有可能有一些全局的事件过滤机制,就可以这么做:
document.onclick
document.onclick = function(){ console.log('document click!'); }; document.getElementById('myEle').onclick = function(){ setTimeout(function(){ console.log('element click!'); },0); };
document click! element click!
The text was updated successfully, but these errors were encountered:
sunmaobin
No branches or pull requests
关于
setTimeout
的一些理解。背景
js不像java一样拥有sleep的功能,也就是将当前线程暂停一段时间后执行,因为js是基于事件机制工作的,所以它提供了
setTimeout
定时任务。也就是说,如果你要实现一个sleep的功能,那也就只能将sleep后的任务,放到
setTimeout
的异步回调函数中执行吧!本文就简单介绍一下
setTimeout
的原理,以及实际工作中的作用。基础
JS是单线程
为什么js要搞成单线程?而不像java一样可以并发呢?根源在于js前期是嵌套在浏览器中的,而浏览器是直接跟用户打交道,对于人看到的结果而言,如果一次性并行执行多个任务,人!是会凌乱的。
当然,随着
node.js
的出现,js多线程不是梦,因为它的出现让大家知道:js不止能跑在浏览器上,还可以用在服务器端。所以,只要在服务器端,那么多线程的事情,终究会解决。虽然现在node.js
全程异步机制已经很高效了!JS是基于事件驱动的
为什么这么说呢?其实对于js而言,所以的任务,全部都进入队列,只不过它将当前执行的任务,叫做
主任务
,而在主任务
中产生的附加的动作全部进入任务队列
,当主线程执行完后,按照FIFO
的原则,依次执行任务队列
中的任务。其实整个事件处理过程 = Main Task + Event Loop[**注意:**loop其实是个while(true),一直无线循环]
setTimeout
setTimeout
的作用,就是改变上面任务队列
中任务的执行顺序的,上文提到,队列中的任务是FIFO
(先进先出) 的。但是!!!如果你给这个任务增加延迟时间,那么情况就不一样啦。也就是说上文提到的
Event Loop
,如果其中各任务都是立即执行的,那么按顺序来,如果有延迟,那么你就靠后一点吧。示例
有了上面解释,大家看看两个例子:
示例1:
结果:
解释:
在执行这几行代码时,主任务(Main Task)上只有一行语句:
而开始出现的代码,由于设置了延迟,所以进入任务队列(Event Loop):
所以,按照执行顺序
Main Task -> Event Loop
,结果也就顺理成章了。示例2:
结果:
解释:
由于
Main Task
是一个死循环,一直执行不完,所以Event Loop
中的任务,就没有机会被执行了。setTimeout(fn,0)
为什么要把延迟时间设置为0,单独拿出来说呢?因为这个在实际开发中,很有意义的!
setTimeout的一个作用,就是让其中执行的任务,脱离当前主任务,延后执行,所以
setTimeout(fn,0)
的一个作用,就是改变当前任务的执行顺序。比如上面的
示例1
,就是活生生的例子。那么,好奇的你又可能要问题了,好生生的我为什么要改变顺序呢?如果要改,我把2个的顺序提前就调转一下就好了嘛,为什么还要
setTimeout
呢,多此一举。你说的太对了,
setTimeout(fn,0)
就是解决这个场景的,即:不能改变事件发生的顺序,而又希望事件按需要的顺序发生。示例:
我们都知道,js的2个特征:
事件捕获
和事件冒泡
。事件捕获
,即:事件会先发生在父元素上,最后钻取到子元素上;事件冒泡
,即:事件会先发生在子元素上,最后上升到父元素上;我们就用
事件捕获
来打个比方:结果:
当你点击页面上的
#myEle
元素的时候,必然会最后触发'document click!'
,因为事件冒泡
。这时候,如果你希望
document.onclick
先执行,因为这里有可能有一些全局的事件过滤机制,就可以这么做:结果:
补充
参考
The text was updated successfully, but these errors were encountered: