任务队列、异步、函数节流

浏览器的单线程模型

在浏览器中,JS 的代码执行是单线程模式。就是只有一个线程去处理 JS 代码,一旦当前队列中有任务在执行,后续的任务都会等到当前任务执行完毕才会执行。

为什么是单线程?因为浏览器在很早就发明出来了,当时考虑的主要就是简单。单线程相较于多线程模式会简单很多,所以 JS 的执行就一直都是一种单线程模式。

这种模式的好处就是实现起来比较简单,不用考虑多线程的执行顺序之类的问题;缺点就是只要有一个任务耗时很长,后面的任务都会排队等待,会拖延整个程序的执行。

在早期的 IE 浏览器中,如果有一个 ajax 请求在等待数据返回的时候,页面经常性的卡死无法操作,甚至都不能滚动页面。

异步

异步任务队列模型

在正常情况下,所有的任务都是放在栈中按顺序执行。但是如果碰到耗时比较久的任务呢??

实际上,在浏览器中,还有一个任务队列(callback queue)。这里存放的都是异步执行的任务。

例如此时我们给某一元素绑定了一个 onClick 事件。绑定的事件我们可以放到主线程中去进行绑定,但是事件的触发我们放到了任务队列中。只有在主线程中的任务都执行完毕后才会执行任务队里列里的任务。

setTimeout 和 setInterval 的操作方式时将绑定的事件移除出本次的事件循环(event loop),等到下一次事件循环的时候去检查是否到了指定时间。如果到了,就执行对应的代码;如果没到,就等到下一轮的事件循环(event loop)时再去判断。

函数节流

为了性能的考虑,有时候有一些频发触发的事件我们需要做一些相对应的节流方式。例如页面滚动的时候,每滚一次就会触发一次,感觉有些浪费性能。

我们可以利用 setTimeout 和 clearTimeout 来进行函数节流。

var timer;
function always(){
    if(timer) clearTimeout(timer);
    timer = setTimeout(function() {
        console.log('Timer...');
    }, 2000);
}

当函数调用时,会进行一个判断:如果当前的值为 false ,那么就给它设置一个 setTimeout ;如果在 setTimeout 的时限之内再次调用的话,就会清除当前的 setTimeout ,并且在重新设置一个 setTimeout 。只有在时限内无动作的话,函数才会直接结果。

这样就实现了函数的节流,减少了后续代码的等待。如果 setTimeout 里面是一个 ajax 请求的话,这个效果会更明显的。节省了请求的时间,也提高了页面的性能。

你可能感兴趣的:(任务队列、异步、函数节流)