间歇调用:后一个间歇调用可能会在前一个间歇调用结束之前启动

      在JavaScript高级程序设计书中提到:一般认为,使用超时调用来模拟间歇调用是一种最佳模式。在开发环境下,很少使用真正的间歇调用,原因是后一个间歇调用可能会在前一个间歇调用结束之前启动。

      但书中并没有具体说明为什么后一个间歇调用可能会在前一个间歇调用结束之前启动。

      查找了一下,有以下几种原因:

1.setInterval(fn,500)则表示的是,每隔500ms执行一次,这里需要注意,不管在500ms时间内fn有没有运行完,500ms之后都将会再次执行fn

2.在setTimeout中的业务会被阻塞到空闲时执行,而setInterval不会受其他业务的阻塞。

具体参考:https://segmentfault.com/q/1010000003060748

3.js是单线程,但是js底层的引擎层是native代码,可以使用多线程。js的异步任务就是在引擎中通过线程池执行完成,然后通知js层。

具体参考:

https://segmentfault.com/q/1010000005704034

https://blog.whyun.com/posts/js/


通过编码验证,结果却和这几种原因不同:

代码:

function syncCode() {
var last = new Date().getTime();
var count = 0;
while (true) {
var now = new Date().getTime();
if (now - last > 1000 * 2) {
last = now;
count++;
console.log('the %dth count.',count);
}
if (count > 3) {
console.log('exist while.');
break;
}
}
}

function syncCode1() {
var last = new Date().getTime();
var count = 0;
while (true) {
var now = new Date().getTime();
if (now - last > 1000 * 2) {
last = now;
count++;
console.log('the %dth count1.',count);
}
if (count > 3) {
console.log('exist while1.');
break;
}
}
}

setTimeout(function() {console.log('setTimeout 0 occured first.');},0);
setTimeout(function() {console.log('setTimeout 0 occured second.');},0);

setInterval(syncCode,1000);
setTimeout(syncCode1,2000);

syncCode();

 


打印结果:

 

setInterval.html:17 the 1th count.
setInterval.html:17 the 2th count.
setInterval.html:17 the 3th count.
setInterval.html:17 the 4th count.
setInterval.html:20 exist while.
setInterval.html:43 setTimeout 0 occured first.
setInterval.html:44 setTimeout 0 occured second.
setInterval.html:17 the 1th count.
setInterval.html:17 the 2th count.
setInterval.html:17 the 3th count.
setInterval.html:17 the 4th count.
setInterval.html:20 exist while.
setInterval.html:34 the 1th count1.
setInterval.html:34 the 2th count1.
setInterval.html:34 the 3th count1.
setInterval.html:34 the 4th count1.
setInterval.html:37 exist while1.
setInterval.html:17 the 1th count.
setInterval.html:17 the 2th count.
setInterval.html:17 the 3th count.
setInterval.html:17 the 4th count.
setInterval.html:20 exist while.
setInterval.html:17 the 1th count.
setInterval.html:17 the 2th count.
setInterval.html:17 the 3th count.
setInterval.html:17 the 4th count.
setInterval.html:20 exist while.

 

结果说明:

1. 同步函数syncCode()最先执行,然后执行

setTimeout(function() {console.log('setTimeout 0 occured first.');},0);
setTimeout(function() {console.log('setTimeout 0 occured second.');},0);
再执行setInterval()中的回调函数syncCode(),最后执行setTimeout()函数中的回调函数syncCode1()。

2.setInterval()是1s执行一次,但syncCode()需要执行8s(4*2s)才结束,从打印中看出,setInterval()是等待syncCode()函数执行完成之后再执行下一次回调函数。而不是在syncCode()函数还未执行完就再次执行下一次回调函数(并未在1s间隔后立即执行回调函数,而是等待回调函数执行8s并结束后,再执行回调函数)。所以setInterval会被同步函数和自己的回调函数阻塞,需等待同步函数或者上一次回调函数执行完成后,再执行下一次回调函数。

3. setTimeout()是2s后执行回调函数syncCode1(),会受到setInterval()的回调函数的阻塞,在第一次setInterval()的回调函数执行完成后(8s)才执行setTimeout()的回调函数syncCode1(),但syncCode1()执行完成后(8s),才第二次执行setInterval()函数的回调函数syncCode(),所以setInterval()函数也会受到setTimeout()的回调函数的阻塞。

 

总结:

setInterval()和setTimeout()都是阻塞性质的,都需要等待前一次调用结束之后再调用,所以不会出现后一个间歇调用可能会在前一个间歇调用结束之前启动的情况。

但书中不是这样写的,我可能理解得还不是很正确,等以后学习相关内容后再更新。。。。。

 

 

posted @ 2018-11-20 21:24  susana123  阅读(524)  评论(0编辑  收藏  举报