(到目前为止)只写了一个非常简单的gulpfile,我对遇到的一个错误感到困惑。
当这个任务的测试失败时,gullow会优雅地退出
gulp.task('test', done => {
new KarmaServer({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, () => done()).start();
});
生产:
Chrome 50.0.2661 (Mac OS X 10.11.3): Executed 11 of 11 (3 FAILED) (0.053 secs / 0.023 secs)
[17:38:02] Finished 'test' after 2.43 s
但当你把它缩小到只通过done
进入因果报应时,它会相当不礼貌地失败
gulp.task('test', done => {
new KarmaServer({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, done).start();
});
生产:
Chrome 50.0.2661 (Mac OS X 10.11.3): Executed 11 of 11 (3 FAILED) (0.066 secs / 0.042 secs)
[17:36:39] 'test' errored after 2.45 s
[17:36:39] Error: 1
at formatError (/usr/local/lib/node_modules/gulp/bin/gulp.js:169:10)
at Gulp.<anonymous> (/usr/local/lib/node_modules/gulp/bin/gulp.js:195:15)
at emitOne (events.js:77:13)
at Gulp.emit (events.js:169:7)
at Gulp.Orchestrator._emitTaskDone (/Users/markstickley/workspace/timewarp/node_modules/gulp/node_modules/orchestrator/index.js:264:8)
at /Users/markstickley/workspace/timewarp/node_modules/gulp/node_modules/orchestrator/index.js:275:23
at finish (/Users/markstickley/workspace/timewarp/node_modules/gulp/node_modules/orchestrator/lib/runTask.js:21:8)
at cb (/Users/markstickley/workspace/timewarp/node_modules/gulp/node_modules/orchestrator/lib/runTask.js:29:3)
at removeAllListeners (/Users/markstickley/workspace/timewarp/node_modules/karma/lib/server.js:336:7)
at Server.<anonymous> (/Users/markstickley/workspace/timewarp/node_modules/karma/lib/server.js:347:9)
at Server.g (events.js:260:16)
at emitNone (events.js:72:20)
at Server.emit (events.js:166:7)
at emitCloseNT (net.js:1518:8)
at doNTCallback1 (node.js:418:9)
at process._tickCallback (node.js:340:17)
有人能解释为什么会发生这种情况吗,因为done
是一个函数,而done
的所有封装版本都调用done
?
进一步的研究表明,Karma使用退出代码解析传递给它的回调(https://karma-runner.github.io/0.13/dev/public-api.html):
var Server = require('karma').Server
var server = new Server({port: 9876}, function(exitCode) {
console.log('Karma has exited with ' + exitCode)
process.exit(exitCode)
})
如果done
被传递给除null
或undefined
之外的任何参数,则该gump将退出运行(https://github.com/gulpjs/gulp/blob/master/docs/API.md#gulptaskname--deps fn):
gulp.task('one', function(cb) {
// do stuff -- async or otherwise
cb(err); // if err is not null and not undefined, the run will stop, and note that it failed
});
因此,当done
作为回调直接传递给Karma时,Karma的退出代码导致gullow提前退出。将其封装在函数中意味着done
仍然被调用,但没有任何参数——导致正常完成。
标记,
有几件事。
我在理解gullow对回调做了什么以及它是如何工作的方面也有同样的问题。首先,我们必须明白,gullow允许你有两种语法。一个是从任务函数返回,gump可以继续执行其后续任务,另一个是必须为相同目的提供回调。这些是等效的:
gulp.task('Returns', function(){
return gulp.src(...).pipe(...)
})
gulp.task('Returns', function(done){
gulp.src(...).pipe(...)
})
另一方面,javascript是一种强大的语言,它允许我们编写一些可怕的、令人恐惧的代码。出于这个原因,我喜欢把事情分解一下。
将第一个函数翻译成人类可读代码:
步骤1
function get_karma_server(){
return new KarmaServer({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}
}
gulp.task('test', done => {
get_karma_server }, () => done()).start();
});
done定义为{}花括号内的内容逗号。但是gullow任务需要一个函数来执行。好的,要执行的函数是执行get_karma_server,它返回服务器的实例和.start()
如果那不会让你呕吐,我不知道会是什么。
这就是它不起作用的原因
如果你不执行这个函数,那么你就没有服务器的实例,这意味着start不是一个未定义的函数,也就是说gump没有得到它的回调。因此出现了所有与回调相关的错误。
步骤2
function get_karma_server(){
return new KarmaServer({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}
}
gulp.task('test', function(done){
get_karma_server().start();
});
仍然相当,但现在它更有意义了done仍然是回调。
步骤3
function get_karma_server(){
return new KarmaServer({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}
}
gulp.task('test', function(){
return get_karma_server().start();
});
同样的函数,但这次我们只是返回,而不是提供回调,如果你不使用它
建议
gulp.task('test', function(the_gulp_callback_aka_done){
// Initialize and get the instance of the server
var karma = require('karma').Server;
// setup your configuration. This could live somewhere else
var config = {
configFile: __dirname + '/karma.conf.js',
singleRun: true
};
// the karma callback
function karma_Callback(){
// Do something here after karma is done running your tests
}
karma.start(config, karma_Callback);
});
要详细。它在运行时一点也不慢,而且理解起来要快得多。
---------------编辑---------------
@马克,我向你道歉。我理解这个问题,但没有传达信息。这不是ES5和ES6的问题。
括号()语法用于执行,对吗?。您可以执行一些不是函数的东西,但javascript会尝试执行它,但会出现错误等等。
在这种情况下,你可以通过名称为因果报应提供一个函数,比如x,然后因果报应会取x,并通过x()调用()。正确的这是因为它期望x是在处理完测试后要调用的函数。因此进行了回电。
现在,在x中,javascript将像执行常规函数一样执行所有内容,但随后它遇到了done的事情,它不知道该怎么办,因为x本身不接受回调。
在代码中:
function x(){
// get things done here
}
function x(callback_for_x){
// get things done here
// ok, I'm done. call the callback_for_x
callback_for_x();
}
在这个版本的x:中使用done
function x(){
// get things done here
// and...
done; // Get ready for some errors
}
在这里使用done会很好。
function x(callback_for_x){
// get things done here
// ok, I'm done. call the callback_for_x
callback_for_x();
}
然而,我们有x的第一个版本作为对karma的回调,这意味着我们必须手动调用done:
function x(){
// get things done here
// and...
done(); // Now gulp can continue because it's callback was called.
}
我希望这更有意义。我讨厌我语无伦次,而且这篇文章的篇幅比预期的要长