可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
in the snippet like this:
gulp.task \"coffee\", ->
gulp.src(\"src/server/**/*.coffee\")
.pipe(coffee {bare: true}).on(\"error\",gutil.log)
.pipe(gulp.dest \"bin\")
gulp.task \"clean\",->
gulp.src(\"bin\", {read:false})
.pipe clean
force:true
gulp.task \'develop\',[\'clean\',\'coffee\'], ->
console.log \"run something else\"
In develop
task I want to run clean
and after it\'s done, run coffee
and when that\'s done, run something else. But I can\'t figure that out. This piece doesn\'t work. Please advise.
回答1:
It\'s not an official release yet, but the coming up Gulp 4.0 lets you easily do synchronous tasks with gulp.series. You can simply do it like this:
gulp.task(\'develop\', gulp.series(\'clean\', \'coffee\'))
I found a good blog post introducing how to upgrade and make a use of those neat features:
migrating to gulp 4 by example
回答2:
By default, gulp runs tasks simultaneously, unless they have explicit dependencies. This isn\'t very useful for tasks like clean
, where you don\'t want to depend, but you need them to run before everything else.
I wrote the run-sequence
plugin specifically to fix this issue with gulp. After you install it, use it like this:
var runSequence = require(\'run-sequence\');
gulp.task(\'develop\', function(done) {
runSequence(\'clean\', \'coffee\', function() {
console.log(\'Run something else\');
done();
});
});
You can read the full instructions on the package README — it also supports running some sets of tasks simultaneously.
Please note, this will be (effectively) fixed in the next major release of gulp, as they are completely eliminating the automatic dependency ordering, and providing tools similar to run-sequence
to allow you to manually specify run order how you want.
However, that is a major breaking change, so there\'s no reason to wait when you can use run-sequence
today.
回答3:
The only good solution to this problem can be found in the gulp documentation which can be found here
var gulp = require(\'gulp\');
// takes in a callback so the engine knows when it\'ll be done
gulp.task(\'one\', function(cb) {
// do stuff -- async or otherwise
cb(err); // if err is not null and not undefined, the orchestration will stop, and \'two\' will not run
});
// identifies a dependent task must be complete before this one begins
gulp.task(\'two\', [\'one\'], function() {
// task \'one\' is done now
});
gulp.task(\'default\', [\'one\', \'two\']);
// alternatively: gulp.task(\'default\', [\'two\']);
回答4:
I generated a node/gulp app using the generator-gulp-webapp Yeoman generator. It handled the \"clean conundrum\" this way (translating to the original tasks mentioned in the question):
gulp.task(\'develop\', [\'clean\'], function () {
gulp.start(\'coffee\');
});
回答5:
run-sequence is the most clear way (at least until Gulp 4.0 is released)
With run-sequence, your task will look like this:
var sequence = require(\'run-sequence\');
/* ... */
gulp.task(\'develop\', function (done) {
sequence(\'clean\', \'coffee\', done);
});
But if you (for some reason) prefer not using it, gulp.start
method will help:
gulp.task(\'develop\', [\'clean\'], function (done) {
gulp.on(\'task_stop\', function (event) {
if (event.task === \'coffee\') {
done();
}
});
gulp.start(\'coffee\');
});
Note: If you only start task without listening to result, develop
task will finish earlier than coffee
, and that may be confusing.
You may also remove event listener when not needed
gulp.task(\'develop\', [\'clean\'], function (done) {
function onFinish(event) {
if (event.task === \'coffee\') {
gulp.removeListener(\'task_stop\', onFinish);
done();
}
}
gulp.on(\'task_stop\', onFinish);
gulp.start(\'coffee\');
});
Consider there is also task_err
event you may want to listen to.
task_stop
is triggered on successful finish, while task_err
appears when there is some error.
You may also wonder why there is no official documentation for gulp.start()
. This answer from gulp member explains the things:
gulp.start
is undocumented on purpose because it can lead to complicated build files and we don\'t want people using it
(source: https://github.com/gulpjs/gulp/issues/426#issuecomment-41208007)
回答6:
According to the Gulp docs:
Are your tasks running before the dependencies are complete? Make sure your dependency tasks are correctly using the async run hints: take in a callback or return a promise or event stream.
To run your sequence of tasks synchronously:
- Return the event stream (e.g.
gulp.src
) to gulp.task
to inform
the task of when the stream ends.
- Declare task dependencies in the second argument of
gulp.task
.
See the revised code:
gulp.task \"coffee\", ->
return gulp.src(\"src/server/**/*.coffee\")
.pipe(coffee {bare: true}).on(\"error\",gutil.log)
.pipe(gulp.dest \"bin\")
gulp.task \"clean\", [\'coffee\'], ->
return gulp.src(\"bin\", {read:false})
.pipe clean
force:true
gulp.task \'develop\',[\'clean\',\'coffee\'], ->
console.log \"run something else\"
回答7:
I was having this exact same problem and the solution turned out to be pretty easy for me. Basically change your code to the following and it should work. NOTE: the return before gulp.src made all the difference for me.
gulp.task \"coffee\", ->
return gulp.src(\"src/server/**/*.coffee\")
.pipe(coffee {bare: true}).on(\"error\",gutil.log)
.pipe(gulp.dest \"bin\")
gulp.task \"clean\",->
return gulp.src(\"bin\", {read:false})
.pipe clean
force:true
gulp.task \'develop\',[\'clean\',\'coffee\'], ->
console.log \"run something else\"
回答8:
tried all proposed solutions, all seem to have issues of their own.
If you actually look into the Orchestrator source, particularly the .start()
implementation you will see that if the last parameter is a function it will treat it as a callback.
I wrote this snippet for my own tasks:
gulp.task( \'task1\', () => console.log(a) )
gulp.task( \'task2\', () => console.log(a) )
gulp.task( \'task3\', () => console.log(a) )
gulp.task( \'task4\', () => console.log(a) )
gulp.task( \'task5\', () => console.log(a) )
function runSequential( tasks ) {
if( !tasks || tasks.length <= 0 ) return;
const task = tasks[0];
gulp.start( task, () => {
console.log( `${task} finished` );
runSequential( tasks.slice(1) );
} );
}
gulp.task( \"run-all\", () => runSequential([ \"task1\", \"task2\", \"task3\", \"task4\", \"task5\" ));
回答9:
Simply make coffee
depend on clean
, and develop
depend on coffee
:
gulp.task(\'coffee\', [\'clean\'], function(){...});
gulp.task(\'develop\', [\'coffee\'], function(){...});
Dispatch is now serial: clean
→ coffee
→ develop
. Note that clean
\'s implementation and coffee
\'s implementation must accept a callback, \"so the engine knows when it\'ll be done\":
gulp.task(\'clean\', function(callback){
del([\'dist/*\'], callback);
});
In conclusion, below is a simple gulp pattern for a synchronous clean
followed by asynchronous build dependencies:
//build sub-tasks
gulp.task(\'bar\', [\'clean\'], function(){...});
gulp.task(\'foo\', [\'clean\'], function(){...});
gulp.task(\'baz\', [\'clean\'], function(){...});
...
//main build task
gulp.task(\'build\', [\'foo\', \'baz\', \'bar\', ...], function(){...})
Gulp is smart enough to run clean
exactly once per build
, no matter how many of build
\'s dependencies depend on clean
. As written above, clean
is a synchronization barrier, then all of build
\'s dependencies run in parallel, then build
runs.
回答10:
I was searching for this answer for a while. Now I got it in the official gulp documentation.
If you want to perform a gulp task when the last one is complete, you have to return a stream:
gulp.task(\'wiredep\', [\'dev-jade\'], function () {
var stream = gulp.src(paths.output + \'*.html\')
.pipe($.wiredep())
.pipe(gulp.dest(paths.output));
return stream; // execute next task when this is completed
});
// First will execute and complete wiredep task
gulp.task(\'prod-jade\', [\'wiredep\'], function() {
gulp.src(paths.output + \'**/*.html\')
.pipe($.minifyHtml())
.pipe(gulp.dest(paths.output));
});
回答11:
For me it was not running the minify task after concatenation as it expects concatenated input and it was not generated some times.
I tried adding to a default task in execution order and it didn\'t worked. It worked after adding just a return
for each tasks and getting the minification inside gulp.start()
like below.
/**
* Concatenate JavaScripts
*/
gulp.task(\'concat-js\', function(){
return gulp.src([
\'js/jquery.js\',
\'js/jquery-ui.js\',
\'js/bootstrap.js\',
\'js/jquery.onepage-scroll.js\',
\'js/script.js\'])
.pipe(maps.init())
.pipe(concat(\'ux.js\'))
.pipe(maps.write(\'./\'))
.pipe(gulp.dest(\'dist/js\'));
});
/**
* Minify JavaScript
*/
gulp.task(\'minify-js\', function(){
return gulp.src(\'dist/js/ux.js\')
.pipe(uglify())
.pipe(rename(\'ux.min.js\'))
.pipe(gulp.dest(\'dist/js\'));
});
gulp.task(\'concat\', [\'concat-js\'], function(){
gulp.start(\'minify-js\');
});
gulp.task(\'default\',[\'concat\']);
Source http://schickling.me/synchronous-tasks-gulp/
回答12:
Gulp and Node use promises.
So you can do this:
// ... require gulp, del, etc
function cleanTask() {
return del(\'./dist/\');
}
function bundleVendorsTask() {
return gulp.src([...])
.pipe(...)
.pipe(gulp.dest(\'...\'));
}
function bundleAppTask() {
return gulp.src([...])
.pipe(...)
.pipe(gulp.dest(\'...\'));
}
function tarTask() {
return gulp.src([...])
.pipe(...)
.pipe(gulp.dest(\'...\'));
}
gulp.task(\'deploy\', function deployTask() {
// 1. Run the clean task
cleanTask().then(function () {
// 2. Clean is complete. Now run two tasks in parallel
Promise.all([
bundleVendorsTask(),
bundleAppTask()
]).then(function () {
// 3. Two tasks are complete, now run the final task.
tarTask();
});
});
});
If you return the gulp stream, you can use the then()
method to add a callback. Alternately, you can use Node\'s native Promise
to create your own promises. Here I use Promise.all()
to have one callback that fires when all the promises resolve.
回答13:
Try this hack :-)
Gulp v3.x Hack for Async bug
I tried all of the \"official\" ways in the Readme, they didn\'t work for me but this did. You can also upgrade to gulp 4.x but I highly recommend you don\'t, it breaks so much stuff. You could use a real js promise, but hey, this is quick, dirty, simple :-)
Essentially you use:
var wait = 0; // flag to signal thread that task is done
if(wait == 0) setTimeout(... // sleep and let nodejs schedule other threads
Check out the post!