由淺入深學習Tapable

文章目錄

  • 由淺入深學習Tapable
  • Tapable是什么
  • Tapable的Hook分類
    • 同步和異步的
  • 使用
    • Sync*同步類型鉤子
      • 基本使用
      • bail
      • Loop
      • Waterfall
  • Async*異步類型鉤子
      • Parallel
      • Series

由淺入深學習Tapable

webpack有兩個非常重要的類:Compiler和Compilation。他們通過注入插件的方式,來監聽webpack的所有生命周期,插件的注入離不開各種各樣的Hook,而他們的Hook是如何得到的呢?其實是創建了Tapable庫中各種Hook的實例。

Tapable是什么

Tapable是一個任務調度庫,它的核心思基于發布訂閱模式是將任務執行邏輯和調度邏輯分離,Tapable在webpack中用于plugin的管理,在可以實現復雜調度邏輯的同時盡可能保證可維護性。

Tapable的機制與Event類似,它可以用來定義各種各樣的鉤子,相當于Event中的事件注冊,但是與Event不同的是,Event中各個事件之間相互不關聯,互不影響,但是tapable注冊的事件之間可以是有關系的,這種關系通過Tapable定義的各個鉤子類來實現。其實,Tapable的核心就是這些鉤子類。因此,我們接下來的重點就是講述這些鉤子類,并實現它們。

Tapable的Hook分類

同步和異步的

  • 以sync開頭的,是同步的Hook
  • 以async開頭的,兩個事件處理回調,不會等待上一次處理回調結束后再執行下一次回調

image-20230812164001985

使用

Tapable的每個子類都是一個用于注冊和觸發事件的鉤子,我們可以查看一下SyncHook實例身上有哪些屬性,找到它注冊事件和觸發事件的屬性。

SyncHook {_args: [],name: undefined,taps: [],interceptors: [],_call: [Function: CALL_DELEGATE],call: [Function: CALL_DELEGATE],   // 用于觸發同步事件的鉤子_callAsync: [Function: CALL_ASYNC_DELEGATE],callAsync: [Function: CALL_ASYNC_DELEGATE],  // 用于觸發異步事件的鉤子_promise: [Function: PROMISE_DELEGATE],promise: [Function: PROMISE_DELEGATE],_x: undefined,compile: [Function: COMPILE],tap: [Function: tap],        // 用于注冊同步事件的鉤子tapAsync: [Function: TAP_ASYNC],  // 用于注冊異步事件的鉤子tapPromise: [Function: TAP_PROMISE],constructor: [Function: SyncHook] 
}

Sync*同步類型鉤子

基本使用

const { SyncHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 創建hooks(webpack完成)syncHook: new SyncHook(["name", "age"]),};// 2. 用hooks監聽事件(自定義plugin)this.hooks.syncHook.tap("event1", (name, age) => {console.log("event1事件監聽執行了:", name, age);});this.hooks.syncHook.tap("event2", (name, age) => {console.log("event2事件監聽執行了:", name, age);});}
}const compiler = new myCompiler();
// 3. 發出去事件(webpack完成)
compiler.hooks.syncHook.call("小張", 20);

結果:

image-20230812164038091

bail

當有返回值時,就不會執行后續的事件觸發了

const { SyncBailHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 創建hooksbailHook: new SyncBailHook(["name", "age"]),};// 2. 用hooks監聽事件(自定義plugin)this.hooks.bailHook.tap("event1", (name, age) => {console.log("event1事件監聽執行了:", name, age);return 123});this.hooks.bailHook.tap("event2", (name, age) => {console.log("event2事件監聽執行了:", name, age);});}
}const compiler = new myCompiler();
// 3. 發出去事件
compiler.hooks.bailHook.call("小張", 20);

輸出結果:

Loop

當返回值為true,就會反復執行該事件,當返回值為undefined或者不返回內容,就退出事件

const { SyncLoopHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 創建hooksloopHook: new SyncLoopHook(["name", "age"]),};let count = 0;// 2. 用hooks監聽事件(自定義plugin)this.hooks.loopHook.tap("event1", (name, age) => {if (count < 5) {console.log("event1事件監聽執行了:", name, age);count++;return true;} else {return;}});this.hooks.loopHook.tap("event2", (name, age) => {console.log("event2事件監聽執行了:", name, age);});}
}const compiler = new myCompiler();
// 3. 發出去事件
compiler.hooks.loopHook.call("小張", 20);

輸出結果:

請添加圖片描述

Waterfall

當返回值不為undefined時,會將這次返回的結果作為下次事件的第一個參數

const { SyncWaterfallHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 創建hookswaterfallHook: new SyncWaterfallHook(["name", "age"]),};// 2. 用hooks監聽事件(自定義plugin)this.hooks.waterfallHook.tap("event1", (name, age) => {console.log("event1事件監聽執行了:", name, age);// return “小李”,小李作為下一個事件的第一個參數return "小李";});this.hooks.waterfallHook.tap("event2", (name, age) => {console.log("event2事件監聽執行了:", name, age);});}
}const compiler = new myCompiler();
// 3. 發出去事件
compiler.hooks.waterfallHook.call("小張", 20);

輸出結果:

請添加圖片描述

Async*異步類型鉤子

Parallel

并行,不會等到上一個事件回調執行結束,才會執行下一次事件處理回調

const { AsyncParallelHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 創建hooksparallelHook: new AsyncParallelHook(["name", "age"]),};// 2. 用hooks監聽事件(自定義plugin)this.hooks.parallelHook.tapAsync("event1", (name, age) => {setTimeout(() => {console.log("event1事件監聽執行了:", name, age);}, 3000);});this.hooks.parallelHook.tapAsync("event2", (name, age) => {setTimeout(() => {console.log("event2事件監聽執行了:", name, age);}, 3000);});}
}const compiler = new myCompiler();
// 3. 發出去事件
compiler.hooks.parallelHook.callAsync("小張", 20);

輸出結果:

請添加圖片描述

Series

串行,會等待上一次異步的Hook,即按照注冊的順序依次執行

const { AsyncSeriesHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 創建hooksseriesHook: new AsyncSeriesHook(["name", "age"]),};// 2. 用hooks監聽事件(自定義plugin)this.hooks.seriesHook.tapAsync("event1", (name, age, callback) => {console.log("event1事件監聽執行了:", name, age);// 這個callback決定下一個事件的執行callback();});this.hooks.seriesHook.tapAsync("event2", (name, age, callback) => {console.log("event2事件監聽執行了:", name, age);// 這個callback決定發出事件中的函數執行callback();});}
}const compiler = new myCompiler();
// 3. 發出去事件
// 第三個參數決定第一個事件的執行
compiler.hooks.seriesHook.callAsync("小張", 20, () => {console.log("所有事件都執行完成啦!");
});

輸出結果:

請添加圖片描述

請添加圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/40430.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/40430.shtml
英文地址,請注明出處:http://en.pswp.cn/news/40430.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CentOS系統環境搭建(一)——Centos7更新

Centos7更新 更新 yum&#xff08;包括centos內核&#xff09; yum update執行后&#xff0c;系統將更新到centos 7.9。 從這一篇文章開始開始&#xff0c;我將開始在centos系統環境搭建&#x1f517;https://blog.csdn.net/weixin_43982359/category_12411496.html中開始對C…

【數據分析入門】Numpy進階

目錄 一、數據重塑1.1 透視1.2 透視表1.3 堆棧/反堆棧1.3 融合 二、迭代三、高級索引3.1 基礎選擇3.2 通過isin選擇3.3 通過Where選擇3.4 通過Query選擇3.5 設置/取消索引3.6 重置索引3.6.1 前向填充3.6.2 后向填充 3.7 多重索引 四、重復數據五、數據分組5.1 聚合5.2 轉換 六、…

回溯算法詳解

目錄 回溯算法詳解 回溯VS遞歸 回溯算法的實現過程 n個結點構造多本節要討論的是當給定 n&#xff08;n>0&#xff09;個結點時&#xff0c;可以構建多少種形態不同的樹。 回溯算法詳解 回溯算法&#xff0c;又稱為“試探法”。解決問題時&#xff0c;每進行一步&#…

主成分分析Python代碼

對于主成分分析詳細的介紹&#xff1a;主成分分析&#xff08;PCA&#xff09;原理詳解https://blog.csdn.net/zhongkelee/article/details/44064401 import numpy as np import pandas as pd標準PCA算法 def standeredPCA(data,N): #data:…

【golang】鏈表(List)

List實現了一個雙向鏈表&#xff0c;而Element則代表了鏈表中元素的結構。 可以把自己生成的Element類型值傳給鏈表嗎&#xff1f; 首先來看List的四種方法。 MoveBefore方法和MoveAfter方法&#xff0c;它們分別用于把給定的元素移動到另一個元素的前面和后面。 MoveToFro…

十種排序算法(附動圖)

排序算法 一、基本介紹 ? 排序算法比較基礎&#xff0c;但是設計到很多計算機科學的想法&#xff0c;如下&#xff1a; ? 1、比較和非比較的策略 ? 2、迭代和遞歸的實現 ? 3、分而治之思想 ? 4、最佳、最差、平均情況時間復雜度分析 ? 5、隨機算法 二、排序算法的分類 …

RabbitMq-1基礎概念

RabbitMq-----分布式中的一種通信手段 1. MQ的基本概念&#xff08;message queue,消息隊列&#xff09; mq:消息隊列&#xff0c;存儲消息的中間件 分布式系統通信的兩種方式&#xff1a;直接遠程調用&#xff0c;借助第三方完成間接通信 消息的發送方是生產者&#xff0c…

面試熱題(二叉樹的鋸齒形層次遍歷)

給你二叉樹的根節點 root &#xff0c;返回其節點值的 鋸齒形層序遍歷 。&#xff08;即先從左往右&#xff0c;再從右往左進行下一層遍歷&#xff0c;以此類推&#xff0c;層與層之間交替進行&#xff09; 輸入&#xff1a;root [3,9,20,null,null,15,7] 輸出&#xff1a;[[3…

MySQL數據庫-字符串函數詳解

前言 MySQL數據庫提供了多種不同類型的函數&#xff0c;用于處理字符串、日期、數值等數據類型&#xff0c;以及實現條件、聚合等操作&#xff0c;下面我們主要介紹字符串函數 CONCAT() 函數 CONCAT() 可用于將多個字符串連接在一起。 示例&#xff1a; SELECT CONCAT(Hell…

C++ STL stack queue

目錄 一.stack 介紹 二.stack 使用 三.stack 模擬實現 普通版本&#xff1a; 適配器版本&#xff1a; 四.queue的介紹 五. queue使用 六.queue模擬實現 七.deque介紹 1.容器適配器 2.deque的簡單介紹 3.deque的缺陷 4.為什么選擇deque作為stack和queue的底層默認容…

System.Text.Encoding不同字符編碼之間進行轉換

System.Text.Encoding 是 C# 中用于處理字符編碼和字符串與字節之間轉換的類。它提供了各種靜態方法和屬性&#xff0c;用于在不同字符編碼之間進行轉換&#xff0c;以及將字符串轉換為字節數組或反之。 在處理多語言文本、文件、網絡通信以及其他字符數據的場景中&#xff0c…

Spring Boot 獲取前端參數

Spring Boot 獲取前端參數 在開發 Web 應用程序時&#xff0c;前端參數是非常重要的。Spring Boot 提供了多種方法來獲取前端參數&#xff0c;本文將介紹其中的一些常用方法。 1. 使用 RequestParam 注解 RequestParam 注解是 Spring MVC 提供的一種常用方式&#xff0c;用于…

C++ 函數

函數是一組一起執行一個任務的語句。每個 C 程序都至少有一個函數&#xff0c;即主函數 main() &#xff0c;所有簡單的程序都可以定義其他額外的函數。 您可以把代碼劃分到不同的函數中。如何劃分代碼到不同的函數中是由您來決定的&#xff0c;但在邏輯上&#xff0c;劃分通常…

pycharm調整最大堆發揮最大

python程序運行時&#xff0c;怎么提高效率&#xff0c;設置pycharm最大堆過程如下&#xff1b; 一、進入設置pycharm最大堆&#xff1b; 二、進入設置pycharm最大堆&#xff1b; 如果8g設置為6g左右&#xff0c;占75%左右最佳

5個實用的 Vue 技巧

在這篇文章中&#xff0c;我們將探討五個實用的 Vue 技巧&#xff0c;這些技巧可以使你日常使用 Vue 編程更高效、更富有成效。無論你是Vue的初學者還是經驗豐富的開發者&#xff0c;這些技巧都能幫助你編寫更清晰、更簡潔、更有效的代碼。那么&#xff0c;讓我們開始吧。 1. …

9.1 C++ STL 排序、算數與集合

C STL&#xff08;Standard Template Library&#xff09;是C標準庫中的一個重要組成部分&#xff0c;提供了豐富的模板函數和容器&#xff0c;用于處理各種數據結構和算法。在STL中&#xff0c;排序、算數和集合算法是常用的功能&#xff0c;可以幫助我們對數據進行排序、統計…

【JVM】JVM中的分代回收

文章目錄 分代收集算法什么是分代分代收集算法-工作機制MinorGC、 Mixed GC 、 FullGC的區別是什么 分代收集算法 什么是分代 在java8時&#xff0c;堆被分為了兩份&#xff1a; 新生代和老年代【1&#xff1a;2】 其中&#xff1a; 對于新生代&#xff0c;內部又被分為了三…

eclipse常用設置

1、調整編輯頁面字體大小 窗口 (Window)- 首選項&#xff08;Preferences&#xff09;- 常規&#xff08;General&#xff09;- 外觀 (Appearence)- 顏色與字體 (Colors And Fonts)&#xff0c;在右邊的對話框里選擇 Java - Java Editor Text Font&#xff0c;點擊出現的修改&…

【ARM 嵌入式 編譯系列 3.3 -- gcc 動態庫與靜態庫的鏈接方法介紹】

文章目錄 1.1 GCC 鏈接器 LD 介紹1.1.1 GCC 鏈接器 LD 常用參數介紹1.2 動態庫和靜態庫介紹1.2.1 動態庫和靜態庫優缺點1.2.2 庫文件鏈接方式1.2.3 ldd 工具介紹1.2.4 靜態庫鏈接時搜索路徑順序1.2.5 動態庫鏈接時、執行時搜索路徑順序1.2.6 頭文件搜索路徑1.2.7 有關環境變量上…

Neo4j之Aggregation基礎

在 Neo4j 中&#xff0c;聚合&#xff08;Aggregation&#xff09;是對數據進行計算、匯總和統計的過程。以下是一些使用聚合函數的常見例子&#xff0c;以及它們的解釋&#xff1a; 計算節點數量&#xff1a; MATCH (p:Person) RETURN count(p) AS totalPersons;這個查詢會計…