JavaScript 异步与同步
首先,说一下什么是异步,什么是同步。
具提详细的定义网上一大堆,我这里仅仅说下我个人的理解。
同步就是,只做一点事情,如果这个过程中需要等待,那么就空闲在哪里,等到得到了想要的结果再去继续处理别的事情。举个例子,在处理一些数据的时候,需要做一个网络请求,获得处理所需的一些东西。所以,要等到网络返回结果后接着去处理剩下的逻辑。
等待的结果是一个漫长的过程,万一没有结果呢?
所以,才有了异步。异步就是一事情做到一半,发现需要等待一段时间,这个时候我们把这个事情暂时放在一边。去作别的事情,等到空闲的时候再去看我们做到一半的事情,有没有具备条件可以寄继续执行。如果有那么就可以去执行它。
我们都知道JavaScript是一门同步执行的语言,但是我们在使用的时候却又很多异步的操作如settimeout, ajax等。这些操作是如何实现的呢?
线程和进程
进程
- 程序运行的实例
- 同一个程序可以产生多个进程
- 一个进程可以包含一个或者多个线程
线程
- 操作系统中能都进行运算调度的最小单位
- 一次只能执行一个任务
- 有自己的调用栈,寄存器环境
- 同一个进程下的线程共享进程的资源
浏览器的进程
- GUI线程 解析html,解析css,构建dom树等
- js引擎线程,解析并执行js,与GUI线程互斥。长时间同步执行js会导致GUI线性停顿,从而感觉浏览器卡主了。
- 定时器触发线程:settimeout setinterval
- 事件触发线程:将满足调试的事件,放入任务队列
- 网络线程:用于处理一些网络请求
定时器
代码
settimeout(() => {
console.log('我执行了')
}, 2000)
上面就是我们使用定时器的一个简单示例,具体执行顺序入下。
- 调用webapi, 这个主要是要请求一个计时器,
- 定时器即使2s,
- 事件触发线程将时间翻入任务对了中
- 主线程通过eventLoop执行
eventLoop是一个任务队列,如果eventLoop中有元素,主线程会不断的轮询eventLoop中是否有元素,如果就将其取出并执行
定时器的弱点
- 定时器并不是严格准时的
- 定时器嵌套5次之后最小间隔不能低于4ms,不同的浏览器中有不同的实现。
定时器的使用场景
- 防抖 节流
- 倒计时
- 定时器动画,有可能出现丢帧
参考文章
https://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html
https://juejin.im/post/5bd7c761518825292d6b0217