前提
- js为什么使用单线程
早期 浏览器主要是操作dom 如果是多线程
假如各个线程都在操作同一个dom浏览器改如何抉择,到底听谁的,
单线程可以避免这个问题
- js为什么需要异步
如果JS中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。
对于用户而言,阻塞就意味着"卡死",这样就导致了很差的用户体验
- js如何实现异步
是通过的事件循环(event loop),理解了event loop机制,就理解了JS的执行机制
- 浏览器的多线程
GUI 渲染线程 (负责渲染浏览器界面HTML元素)
JavaScript引擎线程(主要负责处理Javascript脚本程序,例如V8引擎,GUI渲染线程和JavaScript引擎线程互斥!)
事件触发线程(如鼠标点击、AJAX异步请求等)
定时触发器线程( setTimeout, setInterval )
异步http请求线程
事件轮询处理线程 ( 作用:轮询消息队列,event loop )
主线程和异步线程之间是怎么配合的:
主线程发起一个异步请求(比如http请求),相应的工作线程接收请求并告知主线程已收到通知(异步函数返回);
主线程可以继续执行后面的代码,同时工作线程执行异步任务;
工作线程完成工作之后,通知主线程;
主线程收到通知后,执行一定的动作(调用回调函数);
简答题答案
JS异步编程
- JS是单线程
- 同步编程 只要任务不执行完, 则会一直占用线程 而异步编程则 只是任务的开始和 执行回调时占用主线程 其他操作则通过js主线程之外的资源来处理;
- 相比于同步 异步编程 不会导致主线程阻塞, 主要通过回调来实现, 很容易引起代码嵌套和难以理解的情况
EventLoop
- 一种循环机制 不断去轮询一些队列 从中找到 需要执行的任务并按顺序执行
消息队列
- 用来存放宏任务的队列, 比如定时器时间到了, 定时间内传入的方法引用会存到该队列, ajax回调之后的执行方法也会存到该队列
宏任务
- 不可打断的同步执行的一段js逻辑
- script(整体代码)、setTimeout、setInterval、UI 渲染、 I/O、postMessage、 MessageChannel、setImmediate(Node.js 环境)
微任务
- 不可打断的同步执行的一段js逻辑
- 可在宏任务中添加 但必须等当前宏任务执行完之后才能执行
- 执行时机为 当前宏任务之后 下一个宏任务之前
- Promise 浏览器的MutationObserver NodeJs 的process.nextTick 等都可创建微任务