日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

5调用外部浏览器打开代码_浏览器事件循环

發(fā)布時間:2023/12/2 HTML 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 5调用外部浏览器打开代码_浏览器事件循环 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

瀏覽器運行過程中會同時面對多種任務(wù),用戶交互事件(鼠標、鍵盤)、網(wǎng)絡(luò)請求、頁面渲染等。而這些任務(wù)不能是無序的,必須有個先來后到,瀏覽器內(nèi)部需要一套預(yù)定的邏輯來有序處理這些任務(wù),因此瀏覽器事件循環(huán)誕生了,再次強調(diào),是瀏覽器事件循環(huán),不是javascript事件循環(huán),js只是瀏覽器事件循環(huán)的參與者。

二、事件循環(huán)是什么

瀏覽器把任務(wù)區(qū)分成了 宏任務(wù) 和 微任務(wù) 或者叫 外部任務(wù) 和 內(nèi)部任務(wù) ,內(nèi)部任務(wù)可以理解為js內(nèi)部處理的任務(wù),外部任務(wù)可以認為是瀏覽器處理的任務(wù)。

外部隊列/宏任務(wù)隊列(Task Queue)

也可以叫宏任務(wù)隊列,瀏覽器中的外部事件源包含以下幾種:

  • dom操作(頁面渲染)
  • 用戶交互(鼠標、鍵盤)
  • 網(wǎng)絡(luò)請求(Ajax等)
  • History API操作(history.back、history.go...)
  • 定時器(setTimeout)

這些外部事件源可能很多,為了方便瀏覽器廠商優(yōu)化,HTML標準中明確指出一個事件循環(huán)有一個或多個外部隊列,而每一個外部事件源都有一個對應(yīng)的外部隊列。不同的時間源之間可以有不同的優(yōu)先級(例如在網(wǎng)絡(luò)時間和用戶交互之間,瀏覽器可以優(yōu)先處理鼠標行為,從而讓用戶感覺更加流暢)。

內(nèi)部隊列/微任務(wù)隊列(Microtask Queue)

也可以叫微任務(wù)隊列,指的就是javascript語言內(nèi)部的事件隊列,在HTML標準中,并沒有明確規(guī)定這個隊列的事件源,通常認為有以下幾種:

  • Promise的成功(.then)與失敗(.catch)
  • MutationObserver
  • Object.observe(已廢棄)

以上三種除了第一個,其他兩個可以認為沒有,實際上我們js中能夠使用的就只有promise。

事件循環(huán)模型

先來一張事件循環(huán)處理模型的截圖:

可以看出,每一個事件循環(huán),從外部任務(wù)隊列中拿出一個來執(zhí)行,執(zhí)行完一個外部任務(wù)后立即執(zhí)行內(nèi)部任務(wù)隊列中所有內(nèi)部任務(wù)(清空),然后瀏覽器執(zhí)行一次渲染,然后再次循環(huán)。

一段經(jīng)典代碼

了解了兩種隊列和事件循環(huán)的執(zhí)行模型,下面來一段經(jīng)典代碼:

// 以下代碼會得到什么樣的輸出結(jié)果?console.log('1');setTimeout(function() { console.log('2'); Promise.resolve().then(function() {console.log('3'); });}, 0);Promise.resolve().then(function() { console.log('4');}).then(function() { console.log('5');});console.log('6');

答案是:164523

執(zhí)行順序如下:

  • 由于執(zhí)行當前js代碼這個任務(wù)是一個宏任務(wù),因此首先輸出的是"1",
  • 繼續(xù)執(zhí)行遇到setTimeou,由于setTimeout是一個外部事件源,它內(nèi)部的代碼會被push到TaskQueue中等待下一次事件循環(huán)再執(zhí)行,
  • 當執(zhí)行到promise的 then 或 catchd的時候會將他們按順序追加到本輪事件循環(huán)的末尾,
  • 再繼續(xù)往下執(zhí)行輸出6,宏任務(wù)完成后清空微任務(wù)隊列中的任務(wù),繼而輸出4、5
  • 如果有的話,執(zhí)行渲染任務(wù)后,本次事件循環(huán)結(jié)束
  • 開始執(zhí)行下一個宏任務(wù),也就是第一個setTimeout中的代碼塊,輸出2,然后將promise.then添加到本輪循環(huán)末尾
  • 清空微任務(wù),輸出3

三、瀏覽器與Node.js的事件循環(huán)差異

區(qū)別對比

對于兩者的區(qū)別,來張瞟來的截圖:

這個例子的代碼如下:

setTimeout(()=>{ console.log('1'); Promise.resolve().then(function() {console.log('2'); });});setTimeout(()=>{ console.log('3'); Promise.resolve().then(function() {console.log('4'); });});

這段代碼在瀏覽器和nodejs中的輸出結(jié)果分別是什么呢?

通過前面對瀏覽事件循環(huán)的了解,你應(yīng)該很容易得出在瀏覽器中的輸出結(jié)果是: 1234

那在nodejs中的輸出結(jié)果是什么呢?結(jié)果是在nodejs的 v11.x 之前輸出1324。這之間的原因是瀏覽器有非常多的用戶交互事件,為了用戶體驗更加流暢,必須均勻的處理宏任務(wù)和微任務(wù),而在nodejs中由于并沒有用戶交互事件,為了保證異步事件能夠被均等的執(zhí)行,因此設(shè)計的初衷就是先清空宏任務(wù)隊列再清空微任務(wù)隊列。

不過你應(yīng)該注意到,我上面只說了在 nodejs的 v11.x 之前輸出1324,但是nodejs這個特性在社區(qū)經(jīng)歷了一波開發(fā)者的吐槽之后,node官方在 v11 這個版本緊急修復(fù)了這個問題。所以在 v11.x 以上版本執(zhí)行以上代碼會得到在瀏覽器中一樣的結(jié)果。

setImmediate

先來張瞟來的截圖:

我們再來一個例子:

setTimeout(()=>{console.log('1');Promise.resolve().then(() => console.log('2'));});setTimeout(()=>{ console.log('3'); Promise.resolve().then(() => console.log('4'));});setImmediate(() => {console.log('5'); Promise.resolve().then(() => console.log('6'));});setImmediate(() => {console.log('7'); Promise.resolve().then(() => console.log('8'));});

以上代碼在nodejsV13.x中的執(zhí)行結(jié)果是12345678,接下來我們把順序調(diào)換一下,在第二個位置插入setImmediate

setTimeout(()=>{console.log('1');Promise.resolve().then(() => console.log('2'));});setImmediate(() => {console.log('3'); Promise.resolve().then(() => console.log('4'));});setTimeout(()=>{ console.log('5'); Promise.resolve().then(() => console.log('6'));});setImmediate(() => {console.log('7'); Promise.resolve().then(() => console.log('8'));});

執(zhí)行結(jié)果有一定的概率是12347856,也有一定的概率是 12563478

為啥不同的順序會得到不同的結(jié)果呢?這是由于setTImeout的精度問題導(dǎo)致的,到了這個級別的時間精度,代碼執(zhí)行的時間可能都會導(dǎo)致結(jié)果的不同。下面這張截圖是nodejs官方文檔對于事件循環(huán)順序的展示:

其中timers階段是用于執(zhí)行setTimeout事件的,check階段是用于執(zhí)行setImmediate事件的。Nodejs官方這個所謂事件循環(huán)過程,其實只是完整的事件循環(huán)中Node.js的多個外部隊列相互之間的優(yōu)先級。setTimeout是由event loop檢測系統(tǒng)時間是否到點然后向時間隊列插入一個事件,然后調(diào)用事件的回調(diào)方法。而setImmediate是監(jiān)控UI線程的調(diào)用棧,一旦調(diào)用棧為空則將回調(diào)壓棧。

講了這么多,其實對于上面setTimeout和setImmediate的對比結(jié)果還是有點模糊

推測:對于setImmediate的延時有時比setTimeout的要長,由于setImmediate要先監(jiān)控調(diào)用棧,若調(diào)用棧為空才壓棧,那么在壓棧之前event loop已經(jīng)將setTimeout事件的回調(diào)函數(shù)壓棧了。

好了,以上是這次分享的所有內(nèi)容,對于后面setTimeout和setImmedate的對比沒有的出一個明確的結(jié)果,有興趣的可以一起討論。

總結(jié)

以上是生活随笔為你收集整理的5调用外部浏览器打开代码_浏览器事件循环的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。