Open Twlig opened 2 years ago
js引擎是单线程的,主要分为主线程和事件队列,同步操作是在主线程上执行,一些异步时间或者是未能马上被主程序执行的函数,一般会先放在事件队列当中,等到js主线程空闲了,才会去事件队列取出事情放到主线程。
定时器是属于异步事件,参数里面设置的时间,并不是延迟多少秒去执行回调函数,这个时间代表的是延迟多少秒,把回调函数放到异步队列,等待主线程空闲再被执行。
问题: 使用setInterval()的问题在于,定时器回调函数再次被添加到队列之前还没有完成执行,结果导致事件队列中有多个定时器回调函数,连续运行好几次,而之间没有任何停顿。这样就失去了每隔一段时间触发回调的初衷。
解决方案:js引擎对这个问题的解决方法就是,当使用setInterval()时,仅当事件队列中没有该定时器的回调函数时,才将定时器回调函数添加到事件队列中。确保回调函数执行最小时间间隔为指定间隔。
产生新问题:但是,这样就会导致一些间隔被跳过了。如果功能需求是必须要每个定时器的回调函数都有被执行到,这里就不能满足需求了。
为了避免setInterval()定时器的问题,可以使用链式setTimeout()调用
setTimeout(function fn(){ setTimeout(fn,interval); },interval);
这个模式链式调用了setTimeout(),每次函数执行的时候都会创建一个新的定时器。第二个setTimeout()调用当前执行的函数,并为其设置另外一个定时器。这样做的好处是,在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,就不会产生连续执行回调的情况,也确保了不会有任何缺失的间隔。
参考文章:为什么setTimeout()比setInterval()稳定
js引擎是单线程的,主要分为主线程和事件队列,同步操作是在主线程上执行,一些异步时间或者是未能马上被主程序执行的函数,一般会先放在事件队列当中,等到js主线程空闲了,才会去事件队列取出事情放到主线程。
定时器是属于异步事件,参数里面设置的时间,并不是延迟多少秒去执行回调函数,这个时间代表的是延迟多少秒,把回调函数放到异步队列,等待主线程空闲再被执行。
setInterval()的问题
问题: 使用setInterval()的问题在于,定时器回调函数再次被添加到队列之前还没有完成执行,结果导致事件队列中有多个定时器回调函数,连续运行好几次,而之间没有任何停顿。这样就失去了每隔一段时间触发回调的初衷。
解决方案:js引擎对这个问题的解决方法就是,当使用setInterval()时,仅当事件队列中没有该定时器的回调函数时,才将定时器回调函数添加到事件队列中。确保回调函数执行最小时间间隔为指定间隔。
产生新问题:但是,这样就会导致一些间隔被跳过了。如果功能需求是必须要每个定时器的回调函数都有被执行到,这里就不能满足需求了。
使用setTimeout建立更可靠的间隔执行回调
为了避免setInterval()定时器的问题,可以使用链式setTimeout()调用
这个模式链式调用了setTimeout(),每次函数执行的时候都会创建一个新的定时器。第二个setTimeout()调用当前执行的函数,并为其设置另外一个定时器。这样做的好处是,在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,就不会产生连续执行回调的情况,也确保了不会有任何缺失的间隔。
参考文章:为什么setTimeout()比setInterval()稳定