單線程
JavaScript語言具有單線程的特點(diǎn),同一個(gè)時(shí)間只能做一件事情。這是因?yàn)镴avaScript腳本語言是為了處理頁面中用戶的交互,以及操作DOM而誕生的。如果對(duì)某個(gè)DOM元素進(jìn)行添加和刪除,不同同時(shí)進(jìn)行。應(yīng)該是先添加,再刪除,事件有序。
單線程的特點(diǎn)是所有任務(wù)都需要排隊(duì)進(jìn)行,前一個(gè)任務(wù)結(jié)束,才會(huì)執(zhí)行后一個(gè)任務(wù)。這樣會(huì)導(dǎo)致問題:如果JS執(zhí)行時(shí)間過長(zhǎng),這樣會(huì)導(dǎo)致頁面渲染不連貫,導(dǎo)致頁面渲染加載阻塞。
同步與異步
為了解決這個(gè)問題,利用多核 CPU 的計(jì)算能力,HTML5 提出 Web Worker 標(biāo)準(zhǔn),允許 JavaScript腳本創(chuàng)建多個(gè)線程,JS中出現(xiàn)了同步和異步。
同步
前一個(gè)任務(wù)結(jié)束后再執(zhí)行后一個(gè)任務(wù)
如:
console.log(1);
console.log(2);
console.log(3);
// 1 2 3
異步
在做這件事的同時(shí),你還可以去處理其他事情
如:
console.log(1);
setTimeout(function() {
console.log(3);
},1000);
console.log(2);
// 1 2 3
如果按同步執(zhí)行,要先通過定時(shí)器執(zhí)行完才執(zhí)行下一步,瀏覽器效率大大降低。
所以異步可以先打印 2 等定時(shí)器時(shí)間到再打印3
事件循環(huán)
如果這樣,結(jié)果打印的是什么呢?
console.log(1);
setTimeout(function() {
console.log(3);
},0);
console.log(2);
- JavaScript的同步任務(wù)在主線程中執(zhí)行,形成一個(gè)執(zhí)行棧
- 異步任務(wù)通過回調(diào)函數(shù)實(shí)現(xiàn),把任務(wù)添加到任務(wù)隊(duì)列中
執(zhí)行步驟:
- 先執(zhí)行執(zhí)行棧中的同步任務(wù)
- 異步任務(wù)(回調(diào)函數(shù))放入任務(wù)隊(duì)列中
- 一旦執(zhí)行棧中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會(huì)按次序讀取任務(wù)隊(duì)列中的異步任務(wù),于是被讀取的異步任務(wù)結(jié)束等待狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行
所以上面打印的結(jié)果還是1 2 3
類似的
console.log(1);
document.onclick = function() {
console.log('click');
}
console.log(2);
setTimeout(function() {
console.log(3)
}, 3000)
// 打印1 2 如果點(diǎn)擊了,打印click,無論是否點(diǎn)擊3秒后都打印3
同步任務(wù)放在執(zhí)行棧中執(zhí)行,異步任務(wù)由異步進(jìn)程處理放到任務(wù)隊(duì)列中,執(zhí)行棧中的任務(wù)執(zhí)行完畢會(huì)去任務(wù)隊(duì)列中查看是否有異步任務(wù)執(zhí)行,由于主線程不斷的重復(fù)獲得任務(wù)、執(zhí)行任務(wù)、再獲取任務(wù)、再執(zhí)行,所以這種機(jī)制被稱為事件循環(huán)( event loop)
。
執(zhí)行步驟
文章來源:http://www.zghlxwxcb.cn/news/detail-419124.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-419124.html
到了這里,關(guān)于JS執(zhí)行機(jī)制--同步與異步的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!