最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解JavaScript的事件執(zhí)行機制

 更新時間:2021年09月13日 09:27:59   作者:孟飯飯  
本文主要介紹了JavaScript的事件執(zhí)行機制,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

前言

熟悉事件循環(huán),了解瀏覽器運行機制將對我們理解 JavaScript 的執(zhí)行過程和排查運行問題有很大幫助。以下是總結的一些瀏覽器事件循環(huán)的一些原理和示例。

瀏覽器 JS 異步執(zhí)行的原理

  • JS 是單線程的,也就是同一個時刻只能做一件事情,那么,為什么瀏覽器可以同時執(zhí)行異步任務呢?
  • 因為瀏覽器是多線程的,當 JS 需要執(zhí)行異步任務時,瀏覽器會另外啟動一個線程去執(zhí)行該任務。
  • 也就是說,JS 是單線程的指的是 執(zhí)行JS 代碼的線程只有一個,是瀏覽器提供的 JS 引擎線程(主線程)。瀏覽器中還有定時器線程和 HTTP 請求線程等,這些線程主要不是來跑 JS 代碼的。
  • 比如主線程中需要發(fā)一個 AJAX 請求,就把這個任務交給另一個瀏覽器線程(HTTP 請求線程)去真正發(fā)送請求,待請求回來了,再將 callback 里需要執(zhí)行的 JS 回調交給 JS 引擎線程去執(zhí)行。
  • 即瀏覽器才是真正執(zhí)行發(fā)送請求這個任務的角色,而 JS 只是負責執(zhí)行最后的回調處理。所以這里的異步不是 JS 自身實現(xiàn)的,其實是瀏覽器為其提供的能力。

瀏覽器中的事件循環(huán)

執(zhí)行棧與任務隊列

JS 在解析一段代碼時,會將同步代碼按順序排在某個地方,即執(zhí)行棧,然后依次執(zhí)行里面的函數。
遇到異步任務時就交給其他線程處理,待當前執(zhí)行棧所有同步代碼執(zhí)行完成后,會從一個隊列中去取出已完成的異步任務的回調加入執(zhí)行棧繼續(xù)執(zhí)行。
遇到異步任務時又交給其他線程,.....,如此循環(huán)往復。
而其他異步任務完成后,將回調放入任務隊列中待執(zhí)行棧來取出執(zhí)行。

宏任務和微任務

根據任務的種類不同,可以分為微任務(micro task)隊列和宏任務(macro task)隊列。
事件循環(huán)的過程中,執(zhí)行棧在同步代碼執(zhí)行完成后,優(yōu)先檢查微任務隊列是否有任務需要執(zhí)行,如果沒有,再去宏任務隊列檢查是否有任務執(zhí)行,如此往復。
微任務一般在當前循環(huán)就會優(yōu)先執(zhí)行,而宏任務會等到下一次循環(huán),因此,微任務一般比宏任務先執(zhí)行,并且微任務隊列只有一個,宏任務隊列可能有多個。另外我們常見的點擊和鍵盤等事件也屬于宏任務。

常見宏任務:

  • setTimeout()
  • setInterval()
  • UI交互事件
  • postMessage
  • setImmediate() -- nodeJs

常見微任務:

  • promise.then()、promise.catch()
  • new MutaionObserver()
  • process.nextTick() -- nodeJs

如下示例:

console.log('同步代碼1');
setTimeout(() => {
    console.log('setTimeout')
}, 0)

new Promise((resolve) => {
  console.log('同步代碼2')
  resolve()
}).then(() => {
    console.log('promise.then')
})
console.log('同步代碼3');

// 最終輸出"同步代碼1"、"同步代碼2"、"同步代碼3"、"promise.then"、"setTimeout"

具體分析如下:

  • setTimeout 回調和 promise.then 都是異步執(zhí)行的,將在所有同步代碼之后執(zhí)行;
  • 雖然 promise.then 寫在后面,但是執(zhí)行順序卻比 setTimeout 優(yōu)先,因為它是微任務;
  • new Promise 是同步執(zhí)行的,promise.then 里面的回調才是異步的。

注意: 在瀏覽器中 setTimeout 的延時設置為 0 的話,會默認為 4ms,NodeJS 為 1ms。
微任務和宏任務的本質區(qū)別:

  • 宏任務特征:有明確的異步任務需要執(zhí)行和回調;需要其他異步線程支持。
  • 微任務特征:沒有明確的異步任務需要執(zhí)行,只有回調;不需要其他異步線程支持。

Async/await的運行順序

特點

  • async聲明的函數只是把該函數的return包裝了,使得無論如何都會返回promise對象(非promise會轉化為promise{resolve})。
  • await聲明只能用在async函數中。
    • 當執(zhí)行async函數時,遇到await聲明,會先將await后面的內容按照'平常的執(zhí)行規(guī)則'執(zhí)行完(此處注意,當執(zhí)行函數內容中又遇到await聲明,此時接著執(zhí)行該await聲明內容)。
    • 執(zhí)行完后立馬跳出async函數,去執(zhí)行主線程其他內容,等到主線程執(zhí)行完再回到await處繼續(xù)執(zhí)行后面的內容。

示例

const a = async () => {
  console.log("a");
  await b();
  await e();
};

const b = async () => {
  console.log("b start");
  await c();
  console.log("b end");
};

const c = async () => {
  console.log("c start");
  await d();
  console.log("c end");
};

const d = async () => {
  console.log("d");
};

const e = async () => {
  console.log("e");
};

console.log('start');
a();
console.log('end');

運行結果

個人分析

  • 在當前同步環(huán)境中,先執(zhí)行console.log('start');輸出'start'。
  • 遇到同步函數a(),執(zhí)行a()。
  • a()是sync/await構造,函數內遇到console.log("a") 輸出 'a',遇到await聲明 await b(),為異步函數,進入函數b()內執(zhí)行。(類似的操作,我自己想的)并將 await b()后的內容推入微任務隊列中。我們可以記做[await b()后]。
  • b()是sync/await構造,順序執(zhí)行遇到console.log("c start") 輸出 'c start',遇到await聲明 await c(),為異步函數,進入函數c()內執(zhí)行。并將 await c()后的內容推入微任務隊列中。我們可以記做[await c()后, await b()后]。
  • c()是sync/await構造,順序執(zhí)行遇到console.log("b start") 輸出 'b start',遇到await聲明 await d(),為異步函數,進入函數d()內執(zhí)行。并將 await d()后的內容推入微任務隊列中。我們可以記做[await d()后, await c()后, await b()后]。
  • d()中,順序執(zhí)行遇到console.log("") 輸出 'd',d()函數運行結束。
  • 這是執(zhí)行完 d()后,無可執(zhí)行異步函數,此時進入同步環(huán)境,執(zhí)行 a()后的內容。
  • 遇到console.log("end") 輸出 'end'。此時同步環(huán)境中主線程執(zhí)行完,檢查微任務隊列是否有微任務。
  • 微任務隊列中[await d()后, await c()后, await b()后]有微任務,執(zhí)行await d()后的內容。
  • wait d()后的內容是,console.log("c end"), 輸出 'c end'。此時內容執(zhí)行完畢,再從微任務隊列中[await c()后, await b()后]檢查,執(zhí)行await c()后的內容。
  • 執(zhí)行await c()后的內容,console.log("b end");, 輸出 'b end'。此時內容執(zhí)行完畢,再從微任務隊列中[await b()后]檢查,執(zhí)行await b()后的內容。
  • await d()后的內容是,await e(),遇到await聲明,執(zhí)行e()。并判斷并將 await e()后無運行代碼,不用入微任務隊列。
  • 執(zhí)行e(),順序執(zhí)行console.log("e");,輸出 'e'。此時函數結束。
  • 微任務隊列中[]無微任務,執(zhí)行結束。進入同步環(huán)境。

到此這篇關于深入理解JavaScript的事件執(zhí)行機制的文章就介紹到這了,更多相關JavaScript 事件執(zhí)行機制內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家! 

相關文章

最新評論

玛沁县| 西乡县| 墨竹工卡县| 揭西县| 鄄城县| 葫芦岛市| 霸州市| 宁国市| 大悟县| 永昌县| 忻城县| 桐庐县| 蒙山县| 常熟市| 荆门市| 开阳县| 泗洪县| 张家口市| 师宗县| 静安区| 乳山市| 甘肃省| 五台县| 滦平县| 丹阳市| 永安市| 襄垣县| 清苑县| 全州县| 秭归县| 偃师市| 东宁县| 青浦区| 绍兴县| 龙井市| 黑水县| 延川县| 兴安县| 元阳县| 江都市| 扬州市|