2013-05-14 4 views
9

Теперь у меня есть моя настройка Gruntfile для выполнения некоторой магии автоматического обнаружения, например, для разбора исходных файлов для анализа некоторых источников PHP в roder для динамического определения имен файлов и путей, которые мне нужно знать перед запуском grunt.initConfig().Как выполнить асинхронную операцию перед grunt.initConfig()?

К сожалению, grunt.initConfig() не предназначен для асинхронного запуска, поэтому я не вижу способа выполнить мой асинхронный код, прежде чем я могу его назвать. Есть ли уловка для этого или мне приходится переписывать мои процедуры обнаружения синхронно? Есть ли простой способ блокировать выполнение до моего обратного вызова?

Внутри задачи вальмы есть, конечно, this.async(), но для initConfig() это не работает.

Вот разобранный пример:

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

Есть хорошие идеи, как получить это сделано?

Большое спасибо!

+0

Что произойдет, если вы просто положить grunt.initconfig и grunt.loadnpmtasks и т.д. в функции обратного вызова от функции асинхронной? –

+0

Разве это не то, что я сделал выше? Случается, что grunt не ждет моего обратного вызова, поэтому 'grunt.initConfig()' и т. Д. Не будет вызываться до возвращения клиента grunt. – leyyinad

+0

О да, вы сделали, моя ошибка ... –

ответ

2

Решено путем переписывания, синхронного стиля. ShellJS пригодится, особенно для синхронного выполнения команд оболочки.

5

Я бы сделал это как задачу, так как Grunt синхронизирован или вы можете сделать findSomeFilesAndPaths sync.

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

Большое спасибо Kyle, ваше решение очень полезно для этого минимального примера. На самом деле у меня может быть несколько каталогов для скриптов и таблиц стилей и множество других задач, которые будут известны только во время выполнения, такие как автоматическая загрузка и декомпрессия (все это отлично работает с граблями, но по разным причинам я хочу переключиться на хрюкать) , Я мог бы заставить это работать таким образом, но было бы намного проще и чище иметь готовый объект конфигурации до вызова 'grunt.initConfig()'. Можно ли это сделать? – leyyinad

+0

Поскольку Grunt синхронизируется, вы, к сожалению, не можете не писать свой собственный grunt-cli; который был бы более громоздким, чем вышеупомянутое решение, imo. –

+0

Я думаю, вы правы. В любом случае, просто открыли [вопрос] (https://github.com/gruntjs/grunt/issues/783) на GitHub. – leyyinad

1

Пример того, как можно использовать ShellJS в Грунта:

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