2013-05-14 3 views
9

Jetzt habe ich mein Gruntfile-Setup, um einige automatische Erkennung Magie wie Parsing Quelldateien zu Parsing einige PHP-Quellen in Roder zu dynamisch herauszufinden, Dateinamen und Pfade, die ich wissen müssen, bevor grunt.initConfig() ausgeführt.Wie kann ich eine asynchrone Operation vor grunt.initConfig() durchführen?

Leider grunt.initConfig() scheint nicht asynchron ausgeführt werden, so sehe ich keine Möglichkeit, meine asynchronen Code ausgeführt werden, bevor ich es aufrufen kann. Gibt es einen Trick, um dies zu erreichen, oder muss ich meine Erkennungsroutinen synchron umschreiben? Gibt es eine einfache Möglichkeit, die Ausführung zu blockieren, bevor mein Rückruf angekommen ist?

Inside Grunt Aufgaben gibt es natürlich this.async(), aber für initConfig() das funktioniert nicht.

Hier ist eine abgespeckte Beispiel:

function findSomeFilesAndPaths(callback) { 
    // async tasks that detect and parse 
    // and execute callback(results) when done 
} 

module.exports = function (grunt) { 
    var config = { 
    pkg: grunt.file.readJSON('package.json'), 
    } 

    findSomeFilesAndPaths(function (results) { 
    config.watch = { 
     coffee: { 
     files: results.coffeeDir + "**/*.coffee", 
     tasks: ["coffee"] 
     // ... 
     } 
    }; 

    grunt.initConfig(config); 

    grunt.loadNpmTasks "grunt-contrib-coffee" 
    // grunt.loadNpmTasks(...); 
    }); 
}; 

gute Ideen, wie dies zu tun bekommen?

Vielen Dank!

+0

Was passiert, wenn Sie nur setzen grunt.initconfig und grunt.loadnpmtasks usw. in dem Rückruf von der Asynchron-Funktion? –

+0

Ist das nicht, was ich oben getan habe? Was passiert, ist, dass grunt nicht auf meinen Rückruf wartet, also wird 'grunt.initConfig()' usw. nicht aufgerufen, bevor der grunt-Client zurückkehrt. – leyyinad

+0

Oh ja du hast, mein Fehler ... –

Antwort

2

Gelöst durch Umschreiben, synchronen Stil. ShellJS war praktisch, vor allem für die synchrone Ausführung von Shell-Befehlen.

5

Ich würde es als eine Aufgabe tun, seit Grunt ist synchron oder wenn Sie findSomeFilesAndPaths Sync machen können.

grunt.initConfig({ 
    initData: {}, 
    watch: { 
    coffee: { 
     files: ['<%= initData.coffeeDir %>/**/*.coffee'], 
     tasks: ['coffee'], 
    }, 
    }, 
}); 

grunt.registerTask('init', function() { 
    var done = this.async(); 
    findSomeFilesAndPaths(function(results) { 
    // Set our initData in our config 
    grunt.config(['initData'], results); 
    done(); 
    }); 
}); 

// This is optional but if you want it to 
// always run the init task first do this 
grunt.renameTask('watch', 'actualWatch'); 
grunt.registerTask('watch', ['init', 'actualWatch']); 
+0

Vielen Dank Kyle, deine Lösung ist sehr hilfreich für dieses minimale Beispiel. In der Tat könnte ich mehrere Verzeichnisse für Skripte und Stylesheets und viele andere Aufgaben haben, die nur zur Laufzeit bekannt sind, wie automatische Downloads und Dekomprimierung (all dies funktionierte gut mit Rake, aber aus verschiedenen Gründen möchte ich zu Grunt wechseln) . Ich könnte dies auf diese Weise funktionieren, aber es wäre viel einfacher und sauberer, das gesamte Konfigurationsobjekt vor dem Aufruf von 'grunt.initConfig()' bereit zu haben. Kann dies erreicht werden? – leyyinad

+0

Da Grunt sync ist kannst du leider nicht ohne deinen eigenen grunt-cli schreiben; das wäre mühsamer als die obige Lösung, imo. –

+0

Ich denke du hast Recht. Ich habe sowieso ein [Problem] (https://github.com/gruntjs/grunt/issues/783) auf GitHub geöffnet. – leyyinad

1

Beispiel dafür, wie man ShellJS in Grunt verwenden:

grunt.initConfig({ 
    paths: { 
     bootstrap: exec('bundle show bootstrap-sass').output.replace(/(\r\n|\n|\r)/gm, '') 
    }, 
    uglify: { 
     vendor: { 
      files: { 'vendor.js': ['<%= paths.bootstrap %>/vendor/assets/javascripts/bootstrap/alert.js'] 
     } 
    } 
});