同步和异步的概念
- 同步:可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令(就是实时处理)。
- 异步:执行完函数或方法后,不必阻塞性地等待返回值或信息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动出发委托的异步过程,从而完成一个完整的流程(就是分时处理)。
JS中的同步和异步
-
JS执行机制是单线程
在JS执行中都是单线程执行,所以代码的执行可以说是自上而下,如果前一段的代码出现问题,就会导致下一段代码无法执行,对于用户而言就是卡死现象。
-
JS为什么是单线程的?
举一个简单的例子:
现在又两个线程,process1 process2,若JS是多进程执行的,他们同时对同一个DOM进行操作,process1删除了该DOM,而process2编辑了该DOM,就相当于下达了两个矛盾的命令。
-
JS为什么需要异步
如果JS中不存在异步,只能自上而下单线程执行,那么下面的代码就会被阻塞。对于用户而言,就是卡死现象,这样就会导致很差的用户体验。
-
JS单线程是如何实现异步的?
JS本身是单线程的,并没有异步的特性。但是JS的运行场景是浏览器,浏览器本身的典型的GUI工作线程,GUI工作线程在绝大多数系统中都实现为事件处理,避免阻塞交互,因此产生了JS异步基因。
异步机制是浏览器的两个或以上常驻线程共同完成的,例如异步请求是由两个常驻线程:JS执行线程和事件触发线程共同完成的。所以,所谓的JS单线程和异步更多的应该是属于浏览器的行为,他们之间没有冲突,更不是同一种事物。
JS中的一些异步编程方法
-
回调函数(异步回调中最常见的形式可能就是ajax了)
-
事件监听
任务的执行不取决于代码的顺序,而取决于某个事件是否发生
-
发布订阅模式(又称“观察者模式”)
这种方法的性质与“事件监听”类似,但是明显优于后者。因为我们可以通过查看“消息中心”,了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行
-
promises
Promises对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。
-
async/await
async表示函数中有异步操作,await表示等待着紧跟在后边的表达式的结果。await后面可以跟promise对象和原始类型的值
JS中的宏任务和微任务
JS可以分为同步任务和异步任务,同步任务,是按照顺序进行执行的,但是对于异步任务,会有一个优先级的执行顺序,分别为宏任务和微任务。
-
宏任务和微任务:
○宏任务是主流,当JS开始被执行的时候,就是开启一个宏任务,在宏任务中执行一条一条的指令。
○宏任务可以同时有多个,但是会按顺序一个一个执行。
○每一个宏任务,后面都可以跟一个微任务队列,如果微任务队列中有指令或方法,那么就会执行;如果没有,则开始执行下一个宏观任务,直到所有的宏任务执行完为止。
○为什么有了宏任务,还会有微任务存在?因为宏任务占用性能,当需要一些较早就准备好的方法,排在最后才执行的时候,又不想新增一个宏任务,那么就可以把这些方法一个一个的放在微任务队列里面,在这个宏任务中的代码执行完后,就会执行微任务队列。
-
宏任务包括:
I/O
setTimeout
setInterval
setImmediate
-
微任务包括:
process.nextTick
Promises
Object.observe(废弃)
MutationObserver