須要分析JS執行的效率,因此須要記錄JS的執行時間,經過執行時間分析JS執行效率。可是因爲aync/await使用的盛行,形成在記錄函數執行時間的過程當中,會記錄異步執行的時長,形成時間記錄不許確,沒法分析JS函數真正執行的時間。javascript
看一段代碼java
const asyncFn = ms => new Promise((resolve, reject) => {
setTimeout(resolve, ms);
});
const record = {
start: 0,
time: 0,
};
const fn = async () => {
record.start = performance.now();
await asyncFn(100);
record.time = performance.now() - record.start;
console.log(record.time);
}
fn();
複製代碼
經過瀏覽器控制檯能夠看到輸出結果103.84499999781838,每次執行時間可能會不一樣,但應該都在這個值附近。能夠看出因爲aync/await函數的存在致使fn函數的計時不許確,把異步函數的執行時間也計算在內了。git
在Web端異步函數執行時通常是在請求外部相關接口,此時並不會阻礙Web端執行其餘JS函數,不會形成JS阻塞致使頁面卡頓,因此這種異步函數的執行時間並不在咱們的統計範圍內,咱們只統計web中代碼的執行時間。github
修正方式web
通常咱們能夠經過在async/await函數上下分開計時的方式來解決這個問題,具體能夠看下段代碼:瀏覽器
const asyncFn = ms => new Promise((resolve, reject) => {
setTimeout(resolve, ms);
});
const record = {
start: 0,
time: 0,
};
const fn = async () => {
record.start = performance.now();
record.time = performance.now() - record.start;
await asyncFn(100);
record.start = performance.now();
record.time = performance.now() - record.start;
console.log(record.time);
}
fn();
複製代碼
經過在瀏覽中運行,能夠在控制檯中看到結果,大概是0.010000003385357559,能夠看出確實能夠解決異步函數帶來的影響,可是須要在每一個涉及async/await的地方都要這樣手動處理,你不以爲這樣很麻煩嗎?babel
使用babel AST的能力,經過分析代碼的AST,自動處理async/await的計時問題,避免人工輸入大量重複代碼,減小出錯的機會。markdown
一個優秀的工具是通往目標的階梯,而babel當之無愧是這個階梯。app
點擊跳轉,能夠很方便查看代碼AST結構,有助於理解代碼和AST結構之間的關係,事半功倍。異步
將上面兩段代碼複製進AST,咱們能夠看到上述代碼的AST結構:
對咱們來講,須要重點關注的就是type爲Program的部分,這裏面描述了代碼片斷的AST結構。
寫babel插件以前,須要對babel的運做週期有個清晰的認識,這樣咱們才能知道本身寫的插件何時起做用、達到的效果是什麼,寫插件的過程當中才能遊刃有餘。
Github上對babel的介紹點擊跳轉,能夠查看對babel插件內容的基本介紹,包括AST中各類節點的定義類型、遍歷方式、插件入口等,建議詳細查看一遍。因爲相關內容,該文檔已經比較詳細,編寫插件過程當中,方便進行各類API使用方法的查詢手冊,所以本文中就再也不贅述這部份內容了。
因爲本次只是涉及async/await函數相關操做,咱們將關注type爲AwaitExpression類型的AST節點
按照babel插件的格式,咱們須要默認導出一個函數,該函數接收一個babel對象做爲參數,返回一個具備visitor屬性的對象,具體爲:
export default function (babel) {
return {
visitor: {
AwaitExpression(path) {},
},
};
}
複製代碼
在visitor對象中,定義咱們須要處理的節點類型進行處理便可,具體邏輯能夠參考github上代碼
具體流程能夠參考github上代碼,單元測試部分,主要分爲三個部分:
這樣一個簡單的babel插件就完成了,固然要是真實環境進行使用的話,還須要考慮不少其餘邊界條件,這裏從總體上介紹babel的插件編寫模式,便於後續有類似需求時,能夠快速上手。
能夠在github上找到本文中的代碼示例,方便進行效果測試和新插件開發。