一、js 執(zhí)行機(jī)制
JavaScript語言的一大特點(diǎn)就是單線程,即(同一時(shí)間只能做一件事情)。因?yàn)镴avaScript是為了處理頁面中用戶的交互,以及操作DOM而誕生的。比如對某個(gè)DOM元素進(jìn)行添加和刪除操作。不能同時(shí)進(jìn)行,應(yīng)該先進(jìn)行添加,再進(jìn)行刪除。
單線程就意味著,所有任務(wù)需要排隊(duì),前一個(gè)任務(wù)結(jié)束,才會執(zhí)行后一個(gè)任務(wù)。這樣所導(dǎo)致的問題是∶如果JS執(zhí)行的時(shí)間過長,這樣就會造成頁面的渲染不連貫,導(dǎo)致頁面渲染加載阻塞的感覺。所以HTML5提出Web Worker標(biāo)準(zhǔn),允許JavaScript腳本創(chuàng)建多個(gè)線程,于是,js中出現(xiàn)了 同步 和 異步。
二、同步和異步
同步任務(wù):前一個(gè)任務(wù)結(jié)束后再執(zhí)行后一個(gè)任務(wù),程序的執(zhí)行順序與任務(wù)的排列順序是一致的。
異步任務(wù):多任務(wù)多線程,比如:做一件事的同時(shí),可以去做其他事情。
解釋:
同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧。
異步任務(wù)(js的異步是通過回調(diào)函數(shù)實(shí)現(xiàn)的放入到消息隊(duì)列中)比如:
① 普通的事件。click、resize等
② 資料加載,load、error 等
③ 定時(shí)器,setInterval、setTimeout等
三、執(zhí)行順序
①先執(zhí)行執(zhí)行棧中的同步任務(wù)
② 異步任務(wù)(回調(diào)函數(shù))放入任務(wù)隊(duì)列中
③ 一旦執(zhí)行棧中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會按次序讀取任務(wù)隊(duì)列中的異步任務(wù),于是被讀取的異步任務(wù)結(jié)束等待狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行。
?如圖:
?四、事件循環(huán)
?我們把任務(wù)分為同步任務(wù)和異步任務(wù)。js把異步任務(wù)分為宏任務(wù)和微任務(wù)
在es5之后,JavaScript引入了promise,這樣不需要瀏覽器,JavaScript引擎自身也能夠發(fā)起異步任務(wù)了。
宏任務(wù) 由(瀏覽器、node發(fā)起)、
微任務(wù) 由(js引擎發(fā)起的任務(wù))比如promise(Promise本身是同步的,then/catch的回調(diào)函數(shù)是異步的)
所以我們把代碼可能分為3種
① 同步代碼(js執(zhí)行棧/回調(diào)棧)
② 微任務(wù)的異步代碼(js引擎)
? ?process.nextTick (node)
? ?promise.then( ) catch( )? ? ? ? ? ? ?Promise本身是同步,then/catch的回調(diào)函數(shù)是異步的微任務(wù)
? ?Async/Await?
? ?Object.observer等等
③ 宏任務(wù)的異步代碼
? ?script(代碼塊)
? ?setTimeout/ setInterval定時(shí)器
? ?setImmediate 定時(shí)器
再看三種代碼的執(zhí)行順序:
同步代碼 →→→→微任務(wù)的異步代碼(promise等)? →→→→宏任務(wù)的異步代碼(setTimeout/ setInterval等)
如圖:
五、案列
5-1案例:
<script>
console.log(1);
setTimeout(function() {
console.log(2);
},0)
const p = new Promise((res,rej)=> {
console.log(3);
res(1000)
console.log(4);
}).then(data=> {
console.log(data);
})
console.log(5); //結(jié)果為 1 3 4 5 1000 2
</script>
分析:
?5-2案例:
<script>
new Promise((resolve,reject)=> {
resolve(1)
new Promise((resolve,reject)=> {
resolve(2)
}).then(data => {
console.log(data);
})
}).then(data=> {
console.log(data);
})
console.log(3);
// 3 2 1
</script>
?5-3案例:
<script>
setTimeout(() => {
console.log(1);
}, 0)
new Promise((resolve, reject) => {
console.log(2);
resolve('p1')
new Promise((resolve, reject) => {
console.log(3);
setTimeout(() => {
resolve('setTimeout2')
console.log(4);
}, 0)
resolve('p2')
}).then(data => {
console.log(data);
})
setTimeout(() => {
resolve('setTimeout1')
console.log(5);
}, 0)
}).then(data1 => {
console.log(data1);
})
console.log(6);
// 2 3 6 p2 p1 1 4 5
</script>
?分析:
???????5-4案例:
<script>
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(()=> {
console.log('setTimeout');
},0)
async1();
</script>
分析:
文章來源:http://www.zghlxwxcb.cn/news/detail-735204.html
????????5-5案例:文章來源地址http://www.zghlxwxcb.cn/news/detail-735204.html
<script>
setTimeout(() => {
console.log(0);
}, 0)
new Promise((res, rej) => {
console.log(1);
res();
}).then(() => {
console.log(2);
new Promise((res, rej) => {
console.log(3);
res();
}).then(() => {
console.log(4);
}).then(() => {
console.log(5);
})
}).then(() => {
console.log(6);
})
new Promise((resolve, reject) => {
console.log(7);
resolve(8);
}).then((data) => {
console.log(data);
console.log(9);
})
//結(jié)果為???
</script>
到了這里,關(guān)于js 同步與異步的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!