1>js为什么是单线程
Js的单线程,与它的用途有关。Js作为浏览器脚本语言,它的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定Js同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?之后为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。
1.js异步原因
js选择了成为单线程的语言,它本身就不可能是异步的,但js的宿主环境(比如浏览器)是多线程的,宿主环境通过某种方式(事件驱动)使得js具备了异步的属性。
2.js怎么异步
.js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务形成一个 任务队列排队等候执行,但前端的某些任务是非常耗时的,比如 网络请求,定时器和事件监听,如果让他们和别的任务一样,执行效率会非常的低,甚至导致页面的假死。所以,浏览器为这些耗时任务开辟了另外的线程,主要包括http请求线程,浏览器定时触发器,浏览器事件触发线程,这些任务是异步的。这些异步任务完成后通过回调函数让主线程知道。
具体过程:例如: setTimeout(callback,time);典型的异步函数, 这个函数包括3部分 :
发起函数:setTimeout()
回调函数:calllback
定时时间:time
一个异步任务的发起函数和 回调函数是在主线程中执行的,而其他异步任务,比如这里的计时则是在其他线程中执行的,一个异步任务从被挂起到回调函数被执行由几个步骤组成:
1》主线程执行发起函数,通过发起函数通知相应的线程可以开始执行相应的异步任务,异步任务则在其他线程中执行,不会阻塞js主线程的执行
2》异步任务得到结果后会在任务队列中放置一个回调函数,通常称之为“事件”, 异步任务通过回调函数通知主线程这个异步任务可以继续往下执行,只要主线程一空,程序就会读取任务队列中的事件,任务队列中的事件进入主线程并执行
3.主线程和任务队列
于是,所有任务可以分成两种,一种是 同步任务,另一种是 异步任务。
同步任务指 :在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务:不进入主线程、而进入”任务队列”(task queue)的任务,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
3.event lop
函数的执行就是通过进栈和出栈实现的,比如图中有一个foo()函数,主线程把它推入栈中,在执行函数体时,发现还需要执行上面的那几个函数,所以又把这几个函数推入栈中,等到函数执行完,就让函数出栈。等到stack清空时,说明一个任务已经执行完了, 这时就会从callback queue中寻找下一个人任务推入栈中(这个寻找的过程,叫做event loop,因为它总是循环的查找任务队列里是否还有任务)。
4. Ajax请求是否异步
ajax请求内容的时候是异步的,当请求完成后,会触发请求完成的事件,然后把回调函数放入任务队列中,等到主线程执行该回调函数时还是单线程的。
5. 界面渲染线程是单独开辟的线程,是不是DOM一变化,界面就立刻重新渲染?
如果DOM一变化,界面就立刻重新渲染,效率必然很低,所以 浏览器的机制规定界面渲染 线程和主线程是互斥的,主线程执行任务时,浏览器渲染线程处于挂起状态。