我们常说JS是单线程的,那到底什么是单线程?什么是同步?什么是异步?如何解决回调地狱??
- js阻塞特性:
JS 有个很无语的阻塞特性,就是当浏览器在执行JS 代码时,不能同时做其他任何事情,无论其代码是内嵌的还是外部的 - 同步:你在做一件事情,不能同时去做另外一件事。
- 异步:你在做一件事情,这件事可能会耗时很久,而此时你可以在等待的过程中,去做另外一件事。
比如煮开水这件事吧…在这过程,你担心水沸了而不去做其它事情,就等到水沸腾,那就是同步。
而你觉得这过程耗时蛮久,可以先去做其它事情,比如去扫地,直到水沸腾。
- 单线程:即任务只能是一个个执行的,不能多个任务同时执行,即没有并发性。 js是单线程
你或许会跟我一样疑惑,大家都说JS是单线程的,可是为什么它还有异步代码这么一说。
JS确实是单线程的。但是它运行的环境浏览器内核是多线程的。包括了JS引擎线程、事件触发线程、http请求线程、GUI渲染线程。而各个线程之间是互斥的。比如JS在执行的时候,GUI渲染线程是处于挂起状态。
总不能我在改变DOM节点的时候,你一边进行渲染吧,那会导致性能损耗很大,所以它还是机智的~
平时所说的定时器setTimeout、setInterval和事件触发onclick、onfocus等和http请求都是异步。
JS引擎线程会先执行同步代码,之后才执行处于任务队列里面的异步代码。
例:
此代码输出结果为55555???
<script>
for (var i = 0; i < 5; i++) {
function fun() {
setTimeout(() => {
console.log(i);
}, i * 1000);
}
fun();
}
</script>
setTimeout(code,millisec)
code 必需。 | 要调用的函数后要执行的 JavaScript 代码串。 |
---|---|
millisec 必需 | 在执行代码前需等待的毫秒数 |
因为同步队列的for循环执行完成才轮到异步队列,
每一次for循环的时候,settimeout都执行一次,但是里面的function(闭包函数)没有被执行,而是被放到了任务队列里面,等待执行,
当i累加到5的时候跳出循环。
此时全局只有一个变量i=>5,所以打印出来都是5。
https://www.jianshu.com/p/a81a6ed3ef3a
明天再看
异步过程的构成要素
异步函数实际上很快就调用完成了,但是后面还有工作线程执行异步任务、通知主线程、主线程调用回调函数等很多步骤,
我们把整个过程叫做异步过程,异步函数的调用在整个异步过程中,只是一小部分;
一个异步过程通常是这样的:
-
主线程发起一个异步请求,相应的工作线程接收请求并告知主线程已收到(异步函数返回);
-
主线程可以继续执行后面的代码,同时工作线程执行异步任务;
-
工作线程完成工作后,通知主线程;
-
主线程收到通知后,执行一定的动作(调用回调函数);
异步调用一般分为两个阶段,提交请求和处理结果,这两个阶段之间有事件循环的调用,它们属于两个不同的事件循环(tick),彼此没有关联,
异步调用一般以传入callback的方式来指定异步操作完成后要执行的动作,而异步调用本体和callback属于不同的事件循环;