主頁 >  其他 > 面試率 90% 的JS事件回圈Event Loop,看這篇就夠了!! !

面試率 90% 的JS事件回圈Event Loop,看這篇就夠了!! !

2021-09-02 13:52:07 其他

面試率 90% 的JS事件回圈Event Loop,看這篇就夠了!! !

在這里插入圖片描述

事件回圈(Event Loop)大家應該并不陌生,它是前端極其重要的基礎知識,在平時的討論或者面試中也是一個非常高頻的話題,

理解 JavaScript 的事件回圈往往伴隨著宏任務和微任務、JavaScript 單執行緒執行程序及瀏覽器異步機制等相關問題,而瀏覽器和 NodeJS 中的事件回圈實作也是有很大差別,熟悉事件回圈,了解瀏覽器運行機制將對我們理解 JavaScript 的執行程序和排查運行問題有很大幫助,

一、瀏覽器 JS 異步執行的原理

JS 是單執行緒的,也就是同一個時刻只能做一件事情,那么請你思考:為什么瀏覽器可以同時執行異步任務呢?

因為瀏覽器是多執行緒的,當 JS 需要執行異步任務時,瀏覽器會另外啟動一個執行緒去執行該任務,也就是說,“JS 是單執行緒的”指的是執行 JS 代碼的執行緒只有一個,是瀏覽器提供的 JS 引擎執行緒(主執行緒),瀏覽器中還有定時器執行緒和 HTTP 請求執行緒等,這些執行緒主要不是來跑 JS 代碼的,

比如主執行緒中需要發一個 AJAX 請求,就把這個任務交給另一個瀏覽器執行緒(HTTP 請求執行緒)去真正發送請求,待請求回來了,再將 callback 里需要執行的 JS 回呼交給 JS 引擎執行緒去執行,即瀏覽器才是真正執行發送請求這個任務的角色,而 JS 只是負責執行最后的回呼處理,所以這里的異步不是 JS 自身實作的,其實是瀏覽器為其提供的能力,

在這里插入圖片描述

以 Chrome 為例,瀏覽器不僅有多個執行緒,還有多個行程,如渲染行程、GPU 行程和插件行程等,而每個 tab 標簽頁都是一個獨立的渲染行程,所以一個 tab 例外崩潰后,其他 tab 基本不會被影響,作為前端開發者,主要重點關注其渲染行程,渲染行程下包含了 JS 引擎執行緒、HTTP 請求執行緒和定時器執行緒等,這些執行緒為 JS 在瀏覽器中完成異步任務提供了基礎,

在這里插入圖片描述

二、事件驅動淺析

瀏覽器異步任務的執行原理背后其實是一套事件驅動的機制,事件觸發、任務選擇和任務執行都是由事件驅動機制來完成的,NodeJS 和瀏覽器的設計都是基于事件驅動的,簡而言之就是由特定的事件來觸發特定的任務,這里的事件可以是用戶的操作觸發的,如 click 事件;也可以是程式自動觸發的,比如瀏覽器中定時器執行緒在計時結束后會觸發定時器事件,而本文的主題內容事件回圈其實就是在事件驅動模式中來管理和執行事件的一套流程,

以一個簡單場景為例,假設游戲界面上有一個移動按鈕和人物模型,每次點擊右移后,人物模型的位置需要重新渲染,右移1像素,根據渲染時機的不同我們可以用不同的方式來實作,

在這里插入圖片描述

實作方式一:事件驅動,點擊按鈕后,修改坐標 positionX 時,立即觸發界面渲染的事件,觸發重新渲染,

實作方式二:狀態驅動或資料驅動,點擊按鈕后,只修改坐標 positionX,不觸發界面渲染,在此之前會啟動一個定時器 setInterval,或者利用 requestAnimationFrame 來不斷地檢測 positionX 是否有變化,如果有變化,則立即重新渲染,

瀏覽器中的點擊事件處理也是典型的基于事件驅動,在事件驅動中,當有事件觸發后,被觸發的事件會按順序暫時存在一個佇列中,待 JS 的同步任務執行完成后,會從這個佇列中取出要處理的事件并進行處理,那么具體什么時候取任務、優先取哪些任務,這就由事件回圈流程來控制了,

三、瀏覽器中的事件回圈

執行堆疊與任務佇列

JS 在決議一段代碼時,會將同步代碼按順序排在某個地方,即執行堆疊,然后依次執行里面的函式,當遇到異步任務時就交給其他執行緒處理,待當前執行堆疊所有同步代碼執行完成后,會從一個佇列中去取出已完成的異步任務的回呼加入執行堆疊繼續執行,遇到異步任務時又交給其他執行緒,.....,如此回圈往復,而其他異步任務完成后,將回呼放入任務佇列中待執行堆疊來取出執行,

JS 按順序執行執行堆疊中的方法,每次執行一個方法時,會為這個方法生成獨有的執行環境(背景關系 context),待這個方法執行完成后,銷毀當前的執行環境,并從堆疊中彈出此方法(即消費完成),然后繼續下一個方法,

在這里插入圖片描述

可見,在事件驅動的模式下,至少包含了一個執行回圈來檢測任務佇列是否有新的任務,通過不斷回圈去取出異步回呼來執行,這個程序就是事件回圈,而每一次回圈就是一個事件周期或稱為一次 tick,

宏任務和微任務

任務佇列不只一個,根據任務的種類不同,可以分為微任務(micro task)佇列和宏任務(macro task)佇列,

事件回圈的程序中,執行堆疊在同步代碼執行完成后,優先檢查微任務佇列是否有任務需要執行,如果沒有,再去宏任務佇列檢查是否有任務執行,如此往復,微任務一般在當前回圈就會優先執行,而宏任務會等到下一次回圈,因此,微任務一般比宏任務先執行,并且微任務佇列只有一個,宏任務佇列可能有多個,另外我們常見的點擊和鍵盤等事件也屬于宏任務,

下面我們看一下常見宏任務和常見微任務:

在這里插入圖片描述

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"

上面的代碼將按如下順序輸出為:"同步代碼1"、"同步代碼2"、"同步代碼3"、"promise.then"、"setTimeout",具體分析如下,

(1)setTimeout 回呼和 promise.then 都是異步執行的,將在所有同步代碼之后執行;

順便提一下,在瀏覽器中 setTimeout 的延時設定為 0 的話,會默認為 4ms,NodeJS 為 1ms,

(2)雖然 promise.then 寫在后面,但是執行順序卻比 setTimeout 優先,因為它是微任務;

(3)new Promise 是同步執行的,promise.then 里面的回呼才是異步的,

在這里插入圖片描述

也有人這樣去理解:微任務是在當前事件回圈的尾部去執行;宏任務是在下一次事件回圈的開始去執行,我們來看看微任務和宏任務的本質區別是什么,

我們已經知道,JS 遇到異步任務時會將此任務交給其他執行緒去處理,自己的主執行緒繼續往后執行同步任務,比如 setTimeout 的計時會由瀏覽器的定時器執行緒來處理,待計時結束,就將定時器回呼任務放入任務佇列等待主執行緒來取出執行,前面我們提到,因為 JS 是單執行緒執行的,所以要執行異步任務,就需要瀏覽器其他執行緒來輔助,即多執行緒是 JS 異步任務的一個明顯特征,

我們再來分析下 promise.then(微任務)的處理,當執行到 promise.then 時,V8 引擎不會將異步任務交給瀏覽器其他執行緒,而是將回呼存在自己的一個佇列中,待當前執行堆疊執行完成后,立馬去執行 promise.then 存放的佇列,promise.then 微任務沒有多執行緒參與,甚至從某些角度說,微任務都不能完全算是異步,它只是將書寫時的代碼修改了執行順序而已,

setTimeout 有“定時等待”這個任務,需要定時器執行緒執行;ajax 請求有“發送請求”這個任務,需要 HTTP 執行緒執行,而 promise.then 它沒有任何異步任務需要其他執行緒執行,它只有回呼,即使有,也只是內部嵌套的另一個宏任務,

簡單小結一下微任務和宏任務的本質區別

宏任務特征:有明確的異步任務需要執行和回呼;需要其他異步執行緒支持,

微任務特征:沒有明確的異步任務需要執行,只有回呼;不需要其他異步執行緒支持,

定時器誤差

事件回圈中,總是先執行同步代碼后,才會去任務佇列中取出異步回呼來執行,當執行 setTimeout 時,瀏覽器啟動新的執行緒去計時,計時結束后觸發定時器事件將回呼存入宏任務佇列,等待 JS 主執行緒來取出執行,如果這時主執行緒還在執行同步任務的程序中,那么此時的宏任務就只有先掛起,這就造成了計時器不準確的問題,同步代碼耗時越長,計時器的誤差就越大,不僅同步代碼,由于微任務會優先執行,所以微任務也會影響計時,假設同步代碼中有一個死回圈或者微任務中遞回不斷在啟動其他微任務,那么宏任務里面的代碼可能永遠得不到執行,所以主執行緒代碼的執行效率提升是一件很重要的事情,

在這里插入圖片描述

一個很簡單的場景就是我們界面上有一個時鐘精確到秒,每秒更新一次時間,你會發現有時候秒數會直接跳過 2 秒間隔,就是這個原因,

視圖更新渲染

微任務佇列執行完成后,也就是一次事件回圈結束后,瀏覽器會執行視圖渲染,當然這里會有瀏覽器的優化,可能會合并多次回圈的結果做一次視圖重繪,因此視圖更新是在事件回圈之后,所以并不是每一次操作 Dom 都一定會立馬重繪視圖,視圖重繪之前會先執行 requestAnimationFrame 回呼,那么對于 requestAnimationFrame 是微任務還是宏任務是有爭議的,在這里看來,它應該既不屬于微任務,也不屬于宏任務,

四、NodeJS 中的事件回圈

JS 引擎本身不實作事件回圈機制,這是由它的宿主實作的,瀏覽器中的事件回圈主要是由瀏覽器來實作,而在 NodeJS 中也有自己的事件回圈實作,NodeJS 中也是回圈 + 任務佇列的流程以及微任務優先于宏任務,大致表現和瀏覽器是一致的,不過它與瀏覽器中也有一些差異,并且新增了一些任務型別和任務階段,接下來我們介紹下NodeJS 中的事件回圈流程,

五、NodeJS 中的異步方法

因為都是基于V8 引擎,瀏覽器中包含的異步方式在 NodeJS 中也是一樣的,另外 NodeJS 中還有一些其他常見異步形式,

  • 檔案 I/O:異步加載本地檔案,
  • setImmediate():與 setTimeout 設定 0ms 類似,在某些同步任務完成后立馬執行,
  • process.nextTick():在某些同步任務完成后立馬執行,
  • server.close、socket.on(‘close’,…)等:關倍訓呼,

想象一下,如果上面的形式和 setTimeout、promise 等同時存在,如何分析出代碼的執行順序呢?只要我們理解了 NodeJS 的事件回圈機制,也就清楚了,

六、事件回圈模型

NodeJS 的跨平臺能力和事件回圈機制都是基于 Libuv 庫實作的,你不用關心這個庫的具體內容,我們只需要知道 Libuv 庫是事件驅動的,并且封裝和統一了不同平臺的 API 實作,

NodeJS 中 V8 引擎將 JS 代碼決議后呼叫 Node API,然后 Node API 將任務交給 Libuv 去分配,最后再將執行結果回傳給 V8 引擎,在 Libux 中實作了一套事件回圈流程來管理這些任務的執行,所以 NodeJS 的事件回圈主要是在 Libuv 中完成的,

在這里插入圖片描述

事件回圈各階段

在 NodeJS 中 JS 的執行,我們主要需要關心的程序分為以下幾個階段,下面每個階段都有自己單獨的任務佇列,當執行到對應階段時,就判斷當前階段的任務佇列是否有需要處理的任務,

  • timers 階段:執行所有 setTimeout() 和 setInterval() 的回呼,

  • pending callbacks 階段:某些系統操作的回呼,如 TCP 鏈接錯誤,除 timers、close、setImmediate 的其他大部分回呼在此階段執行,

  • poll 階段:輪詢等待新的鏈接和請求等事件,執行 I/O 回呼等,V8 引擎將 JS 代碼決議并傳入 Libuv 引擎后首先進入此階段,如果此階段任務佇列已經執行完了,則進入 check 階段執行 setImmediate 回呼(如果有 setImmediate),或等待新的任務進來(如果沒有 setImmediate),在等待新的任務時,如果有 timers計時到期,則會直接進入 timers 階段,此階段可能會阻塞等待,

  • check 階段:setImmediate 回呼函式執行,

  • close callbacks 階段:關倍訓呼執行,如 socket.on(‘close’, …),

在這里插入圖片描述

上面每個階段都會去執行完當前階段的任務佇列,然后繼續執行當前階段的微任務佇列,只有當前階段所有微任務都執行完了,才會進入下個階段,這里也是與瀏覽器中邏輯差異較大的地方,不過瀏覽器不用區分這些階段,也少了很多異步操作型別,所以不用刻意去區分兩者區別,代碼如下所示:

const fs = require('fs');

fs.readFile(__filename, (data) => {

    // poll(I/O 回呼) 階段

    console.log('readFile')

    Promise.resolve().then(() => {

        console.error('promise1')

    })

    Promise.resolve().then(() => {

        console.error('promise2')

    })

});

setTimeout(() => {

    // timers 階段

    console.log('timeout');

    Promise.resolve().then(() => {

        console.error('promise3')

    })

    Promise.resolve().then(() => {

        console.error('promise4')

    })

}, 0);

// 下面代碼只是為了同步阻塞1秒鐘,確保上面的異步任務已經準備好了

var startTime = new Date().getTime();

var endTime = startTime;

while(endTime - startTime < 1000) {

    endTime = new Date().getTime();

}

// 最終輸出 timeout promise3 promise4 readFile promise1 promise2

另一個與瀏覽器的差異還體現在同一個階段里的不同任務執行,在 timers 階段里面的宏任務、微任務測驗代碼如下所示:

setTimeout(() => {

  console.log('timeout1')

    Promise.resolve().then(function() {

    console.log('promise1')

  })

}, 0);

setTimeout(() => {

  console.log('timeout2')

    Promise.resolve().then(function() {

    console.log('promise2')

  })

}, 0);

瀏覽器中運行 每次宏任務完成后都會優先處理微任務,輸出“timeout1”、“promise1”、“timeout2”、“promise2”,

NodeJS 中運行 因為輸出 timeout1 時,當前正處于timers階段,所以會先將所有 timer 回呼執行完之后再執行微任務佇列,即輸出“timeout1”、“timeout2”、“promise1”、“promise2”,

上面的差異可以用瀏覽器和 NodeJS 10 對比驗證,是不是感覺有點反程式員?因此 NodeJS 在版本 11 之后,就修改了此處邏輯使其與瀏覽器盡量一致,也就是每個 timer 執行后都先去檢查一下微任務佇列,所以 NodeJS 11 之后的輸出已經和瀏覽器一致了,

nextTick、setImmediate 和 setTimeout

實際專案中我們常用 Promise 或者 setTimeout 來做一些需要延時的任務,比如一些耗時計算或者日志上傳等,目的是不希望它的執行占用主執行緒的時間或者需要依賴整個同步代碼執行完成后的結果,

NodeJS 中的 process.nextTick() 和 setImmediate() 也有類似效果,其中 setImmediate() 我們前面已經講了是在 check 階段執行的,而 process.nextTick() 的執行時機不太一樣,它比 promise.then() 的執行還早,在同步任務之后,其他所有異步任務之前,會優先執行 nextTick,可以想象是把 nextTick 的任務放到了當前回圈的后面,與 promise.then() 類似,但比 promise.then() 更前面,意思就是在當前同步代碼執行完成后,不管其他異步任務,先盡快執行 nextTick,如下面的代碼,因此這里的 nextTick 其實應該更符合“setImmediate”這個命名才對,

setTimeout(() => {

    console.log('timeout');

}, 0);

Promise.resolve().then(() => {

    console.error('promise')

})

process.nextTick(() => {

    console.error('nextTick')

})

// 輸出:nextTick、promise、timeout

接下來我們再來看看 setImmediate 和 setTimeout,它們是屬于不同的執行階段了,分別是 timers 階段和 check 階段,

setTimeout(() => {

  console.log('timeout');

}, 0);

setImmediate(() => {

  console.log('setImmediate');

});

// 輸出:timeout、 setImmediate

分析上面代碼,第一輪回圈后,分別將 setTimeout 和 setImmediate 加入了各自階段的任務佇列,第二輪回圈首先進入timers 階段,執行定時器佇列回呼,然后 pending callbacks和poll 階段沒有任務,因此進入check 階段執行 setImmediate 回呼,所以最后輸出為“timeout”、“setImmediate”,當然這里還有種理論上的極端情況,就是第一輪回圈結束后耗時很短,導致 setTimeout 的計時還沒結束,此時第二輪回圈則會先執行 setImmediate 回呼,

再看這下面一段代碼,它只是把上一段代碼放在了一個 I/O 任務回呼中,它的輸出將與上一段代碼相反,

const fs = require('fs');

fs.readFile(__filename, (data) => {

    console.log('readFile');

    setTimeout(() => {

        console.log('timeout');

    }, 0);

    setImmediate(() => {

        console.log('setImmediate');

    });

});

// 輸出:readFile、setImmediate、timeout

如上面代碼所示:

第一輪回圈沒有需要執行的異步任務佇列;

第二輪回圈 timers 等階段都沒有任務,只有 poll 階段有 I/O 回呼任務,即輸出“readFile”;

參考前面事件階段的說明,接下來,poll 階段會檢測如果有 setImmediate 的任務佇列則進入 check 階段,否則再進行判斷,如果有定時器任務回呼,則回到 timers 階段,所以應該進入 check 階段執行 setImmediate,輸出“setImmediate”;

然后進入最后的 close callbacks 階段,本次回圈結束;

最后進行第三輪回圈,進入 timers 階段,輸出“timeout”,

所以最終輸出“setImmediate”在“timeout”之前,可見這兩者的執行順序與當前執行的階段有關系,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296972.html

標籤:其他

上一篇:深入淺出-探究C#中的IEnumerable、IEnumerator、Yield

下一篇:JavaScript 進階第六章(this與函式的呼叫模式 )

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more