更新时间:2021-06-17 来源:黑马程序员 浏览量:
JavaScript的定时器可以完成一些异步操作。例如,同时设置多个定时器,每个定时器都在3秒后执行一段代码,则3秒后,这些定时器中的代码都会执行。JavaScript的定时器虽然没有Java中的多线程那样强大,但在开发中也能满足大部分的需求。下面针对JavaSeript的执行机制进行讲解。
1、单线程
JavaScript语言的一大特点就是单线程,也就是说,同-一个时间只能做一件事。这是因为JavaScript这门脚本语言诞生的使命所致,即JavaScript是为处理页面中用户的交互,以及操作DOM而诞生的。比如,对某个DOM元素进行添加和删除操作,不能同时进行,应该先进行添加,之后再删除。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务,这样所导致的问题是,如果JavaScript执行的时间过长,就会造成页面的渲染不连贯,导致页面渲染加载有阻塞的感觉。 为了更好地理解,下面我们通过段代码来演示。
console.log(1); setTimeout(function () { console.log(3); }, 5000); console.log(2);
执行上述代码,在控制台会看到程序先输出了1、2,等待5秒后输出3。由此可见,当调用setTimeout()方法后,该方法会立即执行完成,然后执行后面的代码,在控制台中输出2。而为setTimeout()传入的函数,它会在5秒后执行。像这样的操作就称为异步操作。这个异步执行的函数称为回调函数,它的调用时机是由定时器来决定的。
2、同步和异步
为了更好地利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程。于是JavaScript出现了同步和异步的概念。
所谓同步,就是前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法,烧水煮饭,等水开了之后,再去切菜,炒菜。
所谓异步,就是在做一件事件的同时,可以去处理其他的事情。还以做饭为例,异步做法是,在烧水煮饭的同时去切菜炒菜。 同步任务都是在主线程上执行的,会形成一个执行栈,而异步任务是通过回调函数实现的。一般来说,异步任务有3种类型,第1种是普通事件,如click、resize 等;第2种是资源加载,如load、error等;第3种是定时器,如setInterval()、setTimeout()。
3、执行机制
当定时器的时间设为0的时候,就会产生一个问题, 到底是为定时器传入的回调函数优先执行,还是setTimeout()后面的代码优先执行呢?示例代码如下。
console.log(1); setTimeout (function () { console.log(3); }, 0); for (var i = 0, str = ''; i< 900000; i++) { str += i; //利用字符串拼接运算拖慢执行时间 } console.log(2);
上述代码执行后,输出顺序为1、2、3。显然,为定时器传入的回调函数是最后执行的。为了降低偶然性,第5 ~ 7行的代码拖慢了执行时间,但最终结果仍然是3最后输出。 在JavaScript中,同步任务是优先执行的,它们会被放入执行栈中执行,而异步任务(回调函数)则被放人任务队列中,如下图所示。
在上图中,一且执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务就会结束等待状态,进入执行栈,开始执行。因为JavaScript的主线程会不断地重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环( Event Loop )。
猜你喜欢: