產生器執行時環境

撰寫產生器時,最重要的概念之一是如何執行方法,以及在哪個背景中執行方法。

原型方法作為動作

每一個直接附加到產生器原型的原型都被視為一個工作。每一個工作都由 Yeoman 環境執行迴圈依序執行。

換句話說,由 Object.getPrototypeOf(Generator) 傳回的物件上每個函式都會自動執行。

輔助方法和私有方法

現在您知道原型方法被視為一個工作了,您可能會好奇如何定義不會自動呼叫的輔助或私有方法。有以下三種方法可以實現這個目的。

  1. 方法名稱前綴為底線(例如 _private_method)。

       class extends Generator {
         method1() {
           console.log('hey 1');
         }
    
         _private_method() {
           console.log('private hey');
         }
       }
    
  2. 使用實體方法

       class extends Generator {
         constructor(args, opts) {
           // Calling the super constructor is important so our generator is correctly set up
           super(args, opts)
    
           this.helperMethod = function () {
             console.log('won\'t be called automatically');
           };
         }
       }
    
  3. 延伸父產生器

       class MyBase extends Generator {
         helper() {
           console.log('methods on the parent generator won\'t be called automatically');
         }
       }
    
       module.exports = class extends MyBase {
         exec() {
           this.helper();
         }
       };
    

執行迴圈

如果只有一個產生器,則按順序執行工作是可以的。但是當您開始組合產生器時,這是不夠的。

這就是 Yeoman 使用**執行迴圈**的原因。

執行迴圈是一個具有優先順序支援的佇列系統。我們使用 Grouped-queue 模組來處理執行迴圈。

優先順序在您的程式碼中定義為特殊的原型方法名稱。當方法名稱與優先順序名稱相同時,執行迴圈會將方法推入此特殊佇列。如果方法名稱與優先順序不符,則會推入 default 群組。

在程式碼中,它會看起來像這樣

class extends Generator {
  priorityName() {}
}

您也可以使用雜湊而不是單一方法,將多個方法分組到佇列中一起執行

Generator.extend({
  priorityName: {
    method() {},
    method2() {}
  }
});

(請注意,最後這個技巧不適用於 JS class 定義)

可用的優先順序為(按執行順序)

  1. initializing -您的初始化方法(檢查目前的專案狀態、取得組態等)
  2. prompting -您提示使用者輸入選項的地方(您會在這裡呼叫 this.prompt()
  3. configuring -儲存組態並組態專案(建立 .editorconfig 檔案和其他元資料檔案)
  4. default -如果方法名稱與優先順序不符,則會推入到此群組。
  5. writing -您寫入產生器特定檔案的地方(路由、控制器等)
  6. conflicts -處理衝突的地方(內部使用)
  7. install -執行安裝的地方(npm、bower)
  8. end -最後呼叫,清理,說再見

遵循這些優先順序準則,您的產生器就會與其他產生器順利相容。

非同步工作

有許多方法可以暫停執行迴圈,直到工作非同步執行完畢。

最簡單的方法是**傳回 Promise。**當 Promise 解決後,迴圈會繼續執行,或者如果 Promise 失敗,迴圈會引發例外並停止。

如果您依賴的非同步 API 不支援 Promise,則您可以依賴傳統的 this.async() 方式。呼叫 this.async() 會傳回一個函式,在工作完成後呼叫此函式。例如

asyncTask() {
  var done = this.async();

  getUserEmail(function (err, name) {
    done(err);
  });
}

如果 done 函式被帶有錯誤參數呼叫,執行迴圈將會停止,並且例外將會被提出。

接下來該怎麼辦?

現在你對於 Yeoman 執行區塊了解得更多了,你可以繼續閱讀 使用者互動