gulp.task
定义一个使用 Orchestrator 实现的任务(task)。
我看了一下Orchestrator,感觉它就是一个专门处理任务的模块,gulp应该是用了它的部分功能。它在task的功能上,比gulp.task齐全,可以add, start, stop, hasTask, on, onAll这些api。玩儿过jquery的对on的机制应该都不陌生。但是gulp.task感觉只是它的add功能。
用法
gulp.task(name[, deps], fn)
gulp.task('somename', function() {
// 做一些事
});
参数
name
描述:任务的名字,如果你需要在命令行中运行你的某些任务,那么,请不要在名字中使用空格。
类型:String
deps
描述:一个包含任务列表的数组,这些任务会在你当前任务运行之前完成。
类型: Array
gulp.task('mytask', ['array', 'of', 'task', 'names'], function() {
// 做一些事
});
注意: 你的任务是否在这些前置依赖的任务完成之前运行了?请一定要确保你所依赖的任务列表中的任务都使用了正确的异步执行方式:使用一个 callback,或者返回一个 promise 或 stream。
fn
描述:该函数定义任务所要执行的一些操作。
类型:Function
通常来说,它的内部会是这种形式:gulp.src().pipe(someplugin())。
异步任务支持
任务可以异步执行,如果 fn 能做到以下其中一点:
- 接受一个 callback
// 在 shell 中执行一个命令
var exec = require('child_process').exec;
gulp.task('jekyll', function(cb) {
// 编译 Jekyll
exec('jekyll build', function(err) {
if (err) return cb(err); // 返回 error
cb(); // 完成 task
});
});
注意上面的cb(callback)是一个函数,它被作为参数传给了gulp.task的第二个参数(是个函数)。
- 返回一个 stream
gulp.task('somename', function() {
var stream = gulp.src('client/**/*.js')
.pipe(minify())
.pipe(gulp.dest('build'));
return stream;
});
- 返回一个 promise
var Q = require('q');
gulp.task('somename', function() {
var deferred = Q.defer();
// 执行异步的操作
setTimeout(function() {
deferred.resolve();
}, 1);
return deferred.promise;
});
Promise是javascript中一个非常重要的概念,如果你不知道的话,可以阅读一下我写过的一篇文章有一个基本的概念。
注意: 默认的,task 将以最大的并发数执行,也就是说,gulp 会一次性运行所有的 task 并且不做任何等待。如果你想要创建一个序列化的 task 队列,并以特定的顺序执行,你需要做两件事:
- 给出一个提示,来告知 task 什么时候执行完毕,
- 并且再给出一个提示,来告知一个 task 依赖另一个 task 的完成。
对于这个例子,让我们先假定你有两个 task,"one" 和 "two",并且你希望它们按照这个顺序执行:
- 在 "one" 中,你加入一个提示,来告知什么时候它会完成:可以再完成时候返回一个 callback,或者返回一个 promise 或 stream,这样系统会去等待它完成。
- 在 "two" 中,你需要添加一个提示来告诉系统它需要依赖第一个 task 完成。
因此,这个例子的实际代码将会是这样:
var gulp = require('gulp');
// 返回一个 callback,因此系统可以知道它什么时候完成
gulp.task('one', function(cb) {
// 做一些事 -- 异步的或者其他的
cb(err); // 如果 err 不是 null 或 undefined,则会停止执行,且注意,这样代表执行失败了
});
// 定义一个所依赖的 task 必须在这个 task 执行之前完成
gulp.task('two', ['one'], function() {
// 'one' 完成后
});
gulp.task('default', ['one', 'two']);
其实简单的说,就是虽然在default这个任务中,one和two是不分顺序的,但是在two这个任务中,需要依赖one这个任务,所以实际上,当default中的one和two同时开始执行的时候,two并不会马上执行,而是要等到one执行的ok的时候再执行。
回调函数
上面的例子中,多次出现了cb这个回调函数,它是用来干嘛的,代表什么?
其实这个回调函数并不做任何操作意义上的事,而是用来通知gulp这个task完成了,不管完成的怎么样,任务已经可以被忽略了。我更愿意把它称为done(fail),其中的参数如果是null或undefined,则表示成功了,否则表示失败了,里面的内容就是告诉gulp失败的信息。
gulp.task('my_task',function(done){
var data = request();
if(data.error) {
done(data.msg)
}
else {
done();
}
// .. other code ..
});
在done()后面其实还可以执行其他的代码,因为done不是return,程序不会停止执行。但是对于gulp.task而言,它已经接收到任务执行情况的信息了,后面的执行对它来说没什么意义,随便你怎么做都可以。
这也就是为什么上面说如果要让b任务依赖a任务,要给a任务传一个done作为回调函数的原因。因为当b任务开始被执行时,其实先是等待状态,要让a先执行,但是等待归等待,你总得告诉我什么时候开始执行吧,这个“告诉”动作就是done函数,只要在任务执行过程中执行了done函数,就相当于告诉b可以开始执行了。
ok,关于gulp的task这个api就介绍完了,赶紧去自己实践一下。