2013-05-14 12 views
9

Ora ho il mio setup Gruntfile per eseguire alcune funzioni di rilevamento automatico come l'analisi dei file sorgente per analizzare alcuni sorgenti PHP nel roder per capire in modo dinamico i nomi dei file e i percorsi che devo conoscere prima di eseguire grunt.initConfig().Come posso eseguire un'operazione asincrona prima di grunt.initConfig()?

Purtroppo lo grunt.initConfig() non sembra essere pensato per essere eseguito in modo asincrono, quindi non vedo alcun modo di eseguire il mio codice asincrono prima di poterlo chiamare. C'è un trucco per realizzare questo o devo riscrivere le mie routine di rilevamento in modo sincrono? C'è un modo semplice per bloccare l'esecuzione prima che il mio callback sia arrivato?

All'interno di attività grunt c'è ovviamente this.async(), ma per initConfig() non funziona.

Ecco un esempio ridotta:

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(...); 
    }); 
}; 

Delle buone idee su come ottenere questo fatto?

Grazie mille!

+0

Cosa succede se hai appena messo grunt.initconfig e grunt.loadnpmtasks ecc nella richiamata dalla funzione asincrona? –

+0

Non è quello che ho fatto sopra? Quello che succede è che grunt non aspetta la mia callback, quindi 'grunt.initConfig()' ecc non sarà chiamato prima che il client grunt ritorni. – leyyinad

+0

Oh sì, l'ho fatto, mio ​​errore ... –

risposta

2

Risolto tramite riscrittura, stile sincrono. ShellJS è stato utile, soprattutto per l'esecuzione sincrona dei comandi della shell.

5

Lo farei come un'attività poiché Grunt è sincronizzato o se è possibile effettuare la sincronizzazione findSomeFilesAndPaths.

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

Grazie mille Kyle, la tua soluzione è molto utile per quell'esempio minimo. In effetti potrei avere più directory per script e fogli di stile e molte altre attività che saranno conosciute solo in fase di esecuzione, come download automatici e decompressione (tutto ciò ha funzionato bene con il rake, ma per vari motivi voglio passare a grunt) . Potrei farlo funzionare in questo modo, ma sarebbe molto più semplice e pulito avere l'intero oggetto di configurazione pronto prima di chiamare 'grunt.initConfig()'. Questo può essere realizzato? – leyyinad

+0

Poiché Grunt è sincronizzato, sfortunatamente non puoi scrivere senza il tuo grunt-cli; quale sarebbe più ingombrante della soluzione di cui sopra, imo. –

+0

Immagino che tu abbia ragione. Ho appena aperto un [numero] (https://github.com/gruntjs/grunt/issues/783) su GitHub, comunque. – leyyinad

1

Esempio di come si potrebbe usare ShellJS in Grunt:

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'] 
     } 
    } 
}); 
Problemi correlati