「这是我参与2022首次更文挑战的第32天,活动详情查看:2022首次更文挑战」
同步异步
首先要明确一点, 异步是绝对的,同步是相对的。
意思就是说,下一次轮循相对于这一次就是异步的,把任务排到下一次轮循,是不会阻塞当前这一次的。 所以说异步是绝对的。
那么同步的相对就是指,在一轮任务中,才会出现同步代码。简单的说就是上一行代码和下一行代码是有可能相对同步的, 上一行执行完毕之后,才会执行下一行。
while(new Date().getMinutes <10){ console.log(10)};
alert('OK')
微任务和宏任务
按前面所说,微任务相对于宏任务就是异步,但是微任务内部的代码它是同步的。
在一次轮回中,总是先开始执行宏任务。待得宏任务栈空,再去查看微任务队列是否有,有就执行。 之所以说是队列, 因为先注册的微任务会先执行,后注册的会后执行。 如果微任务执行完毕,这一轮循环就结束了。 js引擎就可以休息了。
接下来就是渲染的事了。 渲染和js执行是互斥,js执行完毕,尘埃落定才能开始渲染。 从这个角度来说,js的执行会阻塞渲染,也就是我们常看到的页面空白。
所谓异步宏任务就是说,把这个任务记下来,下次轮循的再说。 下次再执行。同步宏任务,说的就是当前这一次的整体代码,除开定时器,期约等等。
另外,由于,微任务是紧跟着宏任务之后的,并且会一次性清空微任务队列。所以从这个角度来说,宏任务实际上会阻塞微任务的执行。因为当前宏任务栈如果不空的话,永远不会执行微任务。 同样,微任务队列如果不清空,永远不会开启下一轮宏任务。
也有人把微任务看做是宏任务的一部分,只不过微任务是在主体程序执行完毕再执行。
同步代码是会在同一个执行栈的,这样就会形成栈的嵌套,也就是我们平常遇到的函数里面套函数、递归等。
宏任务自己有一个执行栈,而微任务不会放在同一个栈里,不会形成嵌套,所以宏任务不必等微任务执行完毕才执行。在宏任务弹栈之后,才会执行微任务,这时微任务才入栈。也有一种说法认为,微任务是包含在宏任务内的,按这种说法,微任务就是一轮宏任务中的异步任务。
js 会不会阻塞css的加载? css会阻塞js, 我知道浏览器的渲染是在两次宏之间,也知道css加载是在渲染里面,但是我之前确实不认为这算是阻塞, 因为他们两互不干涉,但是互相等待啊,但是css加载的时间越久,js的执行就会越往后延。这样看。css的加载也会阻塞js。
小结
js的运行,就是一个周期函数,自变量是时间,因变量是执行的任务。 我们可以认为,浏览器两次刷新的这个时间间隔,就是一个完整的周期。
在一个周期内,浏览器会先执行js,然后进行渲染。
执行js,又分为宏任务栈,和微任务栈 。 一般都会先执行宏任务,再执行微任务。
定时器 和请求动画帧 都是把任务加到下一个周期的宏任务队列中。
不考虑嵌套的情况,一般的微任务都是添加到本次周期的微任务队列中的 。
一个周期完了,就会开始下一个周期,就这样周而复始,生生不息。
当然了,中途如果卡住了,这个就是所谓的阻塞了。 典型的阻塞有,死循环,alert。