閱讀655 返回首頁    go 微軟 go windows


《JavaScript開發框架權威指南》——2.4 處理任務

本節書摘來自異步社區《JavaScript開發框架權威指南》一書中的第2章,第2.4節,作者:【美】Tim Ambler , Nicholas Cloud著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看

2.4 處理任務

對於配置來說,Grunt的config()方法既是“getter”,也是“setter”。在清單中,我們可以看到一個基本的Grunt任務是如何通過此方法來存取配置的。

清單2-9 管理一個基本Grunt任務的配置

module.exports = function(grunt) {

    grunt.config('basic-task', {
        'message': 'Hello, world.'
    });

    grunt.registerTask('basic-task', function() {
        grunt.log.writeln(grunt.config('basic-task.message'));
    });
};

注意:
 

清單2-9中“點記法”(dot notation)是用來訪問多級嵌套的配置參數的。采用同樣的方式,點記法還可以用於設置多級嵌套的配置參數值。而且無論在哪裏遇到不存在的配置路徑,Grunt都會為其創建一個新的空對象,而不拋出異常。
2.4.2 任務描述
隨著時間的推移,項目複雜性會逐漸增加,因此需要不斷添加新的Grunt任務。但是隨著任務的增多,任務的可用性、用途以及調用方法等越來越難以追蹤。幸運的是,Grunt已經為我們提供了一條解決此問題的途徑。如清單所示,我們可以為任務設定相應的描述。

清單2-10 為Grunt任務設置描述

// example-task-description/Gruntfile.js

module.exports = function(grunt) {

    grunt.config('basic-task', {

        'message': 'Hello, world.'
    });
    grunt.registerTask('basic-task', 'This is an example task.', function() {
        grunt.log.writeln(grunt.config('basic-task.message'));
    });

    grunt.registerTask('default', 'This is the default task.', ['basic-task']);
};

要為任務設置描述,隻要在調用registerTask()時多傳入一個參數即可。如果在命令行中請求幫助信息,Grunt就會將這些任務描述打印出來。清單截取了其中的一個片段。

清單2-11 在命令行中請求幫助信息

$ grunt --help
...
Available tasks
    basic-task This is an example task.
        default This is the default task.
...

2.4.3 異步任務
默認情況下,Grunt任務是同步執行的。隻要任務函數返回,即可認為任務已經執行完畢。然而,有時候我們需要在任務中使用異步函數,而且必須等待其執行完畢才能將控製權交還給Grunt。清單中展示了這個問題的解決方法。在任務中調用async()方法將通知Grunt此任務是異步執行的。該方法返回一個回調函數,用於在任務完成時調用。在此之前,Grunt暫不會執行任何額外的任務。

清單2-12 異步Grunt任務

// example-async/tasks/list-files.js

var glob = require('glob');
module.exports = function(grunt) {

    grunt.registerTask('list-files', function() {

        /**
         * Grunt將一直等待我們調用done()函數來通知它異步任務執行完畢。
         */
        var done = this.async();
        glob('*', function(err, files) {
            if (err) {
                grunt.fail.fatal(err);
            }
            grunt.log.writeln(files);
            done();
        });
    });
};

2.4.4 任務依賴
對於複雜的Grunt工作流程,我們最好將其看作由一係列協同工作以達成最終結果的任務步驟組成。這種情況下,為任務指定一個或多個其他任務作為先決條件往往很有幫助,如清單所示。

清單2-13 聲明任務依賴

// example-task-dependency/tasks/step-two.js

module.exports = function(grunt) {
    grunt.registerTask('step-two', function() {
        grunt.task.requires('step-one');
    });
};

本例中,step-two任務要求step-one必須在其之前運行。任何試圖直接調用step-two的行為都將導致錯誤發生,如清單所示。

清單2-14 依賴項運行之前直接運行任務導致Grunt報錯

$ grunt step-two
Running "step-two" task
Warning: Required task "step-one" must be run first. Use --force to continue.

Aborted due to warnings.

2.4.5 多任務
除基本任務之外,Grunt還支持“多任務”(multi-task)。多任務差不多是Grunt裏最複雜的概念,所以如果你一開始感到困惑,別擔心,這很正常。事實上,隻要看過幾個例子之後,它們的用途就會變得清晰起來,你也會從此踏上精通Grunt的道路。繼續之前,還是讓我們先看一個比較簡單的多任務示例及其配置(見清單)。

清單2-15 Grunt多任務

// example-list-animals/tasks/list-animals.js

module.exports = function(grunt) {
    /**
     * Our multi-task's configuration object. In this example, 'mammals'
     * and 'birds' each represent what Grunt refers to as a 'target.'
     */
    grunt.config('list-animals', {
        'mammals': {
            'animals': ['Cat', 'Zebra', 'Koala', 'Kangaroo']
        },
        'birds': {
            'animals': ['Penguin', 'Sparrow', 'Eagle', 'Parrot']
        }
    });

    grunt.registerMultiTask('list-animals', function() {
        grunt.log.writeln('Target:', this.target);
        grunt.log.writeln('Data:', this.data);
    });
};

多任務的使用極其靈活,其設計目的就是在單個項目中支持多種配置(稱作“目標”,targets)。清單中的多任務有兩個目標:mammals和birds。如清單所示,該任務可以按照任一目標運行。

清單2-16 按照特定目標運行清單中的任務

$ grunt list-animals:mammals
Running "list-animals:mammals" (#list-animals) task
Target: mammals
Data: { animals: [ 'Cat', 'Zebra', 'Koala', 'Kangaroo' ] }

Done, without errors.

運行多任務時也可以不傳入任何參數。這種情況下,任務會為每個可用的目標都運行一次。清單展示了在不指定目標的情況下運行多任務所產生的結果。

清單2-17 在不指定目標的情況下,運行清單中的多任務

$ grunt list-animals
Running "list-animals:mammals" (#list-animals) task
Target: mammals
Data: { animals: [ 'Cat', 'Zebra', 'Koala', 'Kangaroo' ] }

Running "list-animals:birds" (#list-animals) task
Target: birds
Data: { animals: [ 'Penguin', 'Sparrow', 'Eagle', 'Parrot' ] }

上述示例中,我們的多任務運行了兩次,每個目標一次(mammals和birds)。注意在清單中,我們的多任務引用了兩個屬性:this.target和this.data。這些屬性使得多任務能夠獲取與當前正在運行的目標相關的信息。

2.4.6 多任務選項
在配置多任務時,任何存儲在options鍵下的值(見清單)都會受到特殊處理。

清單2-18 Grunt多任務與Options配置項

// example-list-animals-options/tasks/list-animals.js

module.exports = function(grunt) {

    grunt.config('list-animals', {
        'options': {
            'format': 'array'
        },
        'mammals': {
            'options': {
                'format': 'json'
            },
            'animals': ['Cat', 'Zebra', 'Koala', 'Kangaroo']
        },
        'birds': {
            'animals': ['Penguin', 'Sparrow', 'Eagle', 'Parrot']
        }
    });

    grunt.registerMultiTask('list-animals', function() {

        var options = this.options();

        switch (options.format) {
            case 'array':
                grunt.log.writeln(this.data.animals);
            break;
            case 'json':
                grunt.log.writeln(JSON.stringify(this.data.animals));
            break;
            default:
                grunt.fail.fatal('Unknown format: ' + options.format);
            break;
        }
    });

};

多任務選項為開發者提供了一種機製,即為任務定義和全局選項可以被目標任務的選項覆寫。本例中,動物列表的全局選項format在任務層級被定義為'array'。目標mammals將其覆寫為'json',但是目標birds沒有。這樣,mammals將顯示為JSON串,而birds則繼承全局選項的設定仍然顯示為數組。

今後你遇到的絕大多數Grunt插件都會是可配置的多任務。由此而來的靈活性使得我們可以針對不同的應用環境,以不同的方式運行同一個任務。一個常見的情景就是為不同的構建環境創建不同的輸出目標。例如,在編譯程序時,針對本地開發環境和產品發布可以選用不同的任務運行配置。

2.4.7 模板配置
Grunt配置對象支持配置嵌入式的模板字符串,可用於之後的其他配置。Grunt支持的模板格式遵循Lodash和Underscore,具體細節會涵蓋在後續的章節中。清單和清單中的示例顯示了該功能可以如何使用。

清單2-19 Gruntfile樣例,Grunt配置對象的pkg鍵中保存了項目package.json的內容

// example-templates/Gruntfile.js

module.exports = function(grunt) {
    grunt.initConfig({
        'pkg': grunt.file.readJSON('package.json')
    });
    grunt.loadTasks('tasks');
    grunt.registerTask('default', ['test']);
};

清單2-20 使用自身配置的後續加載任務,可以使用模板來引用其他配置

// example-templates/tasks/test.js

module.exports = function(grunt) {
    grunt.config('test', {
        'banner': '<%= pkg.name %>-<%= pkg.version %>'
    });
    grunt.registerTask('test', function() {
        grunt.log.writeln(grunt.config('test.banner'));
    });
};

清單展示了Gruntfile配置樣例,其通過使用一係列與文件係統交互的內置方法,實現了加載項目Package.Json文件的內容,這些內置方法會在本章後續內容中討論。文件內容隨後存儲在Grunt配置對象的pkg屬性中。在清單中可以看到,通過使用配置模板,任務能夠直接引用配置對象pkg的信息。

2.4.8 命令行選項

通過如下格式可以為Grunt傳遞額外配置項。

$ grunt count --count=5
清單中的例子展示了Grunt任務是如何通過grunt.option()方法獲取信息的。從清單可以看到調用該任務的結果。

清單2-21 簡單Grunt任務計數到指定數字

// example-options/tasks/count.js

module.exports = function(grunt) {

    grunt.registerTask('count', function() {
        var limit = parseInt(grunt.option('limit'), 10);
        if (isNaN(limit)) grunt.fail.fatal('A limit must be provided (e.g. --limit=10)');
        console.log('Counting to: %s', limit);
        for (var i = 1; i <= limit; i++) console.log(i);
    });
};
清單2-22 執行清單中任務的輸出結果

$ grunt count --limit=5
Running "count" task
Counting to: 5
1
2
3
4
5

Done, without errors.

2.4.9 提供反饋
為了在執行任務時為用戶提供反饋信息,Grunt提供了一些內置方法,其中某些方法你已經在本章中看過。當然,我們不會在此處列出所有方法,但表中列出了一些常用的。
screenshot

2.4.10 錯誤處理
在任務執行的過程中,會遇到錯誤。當遇到這種情況時,知道如何合理地處理它們是很重要的。當麵對一個錯誤時,開發者需要使用Grunt的錯誤API。它很易於使用,因為它隻提供了兩個方法(見表)。
screenshot

最後更新:2017-06-06 07:32:51

  上一篇:go  開發者的實用 Vim 插件(二)
  下一篇:go  科學音頻處理(三):如何使用 Octave 的高級數學技術處理音頻文件