只写一个(到目前为止)非常简单的gulpfile,我对我遇到的错误感到困惑。
当测试因此任务失败时,gulp正常退出
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
传递给Karma时,它就会失败而且非常失败
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
?
答案 0 :(得分:4)
进一步的研究表明,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
(https://github.com/gulpjs/gulp/blob/master/docs/API.md#gulptaskname--deps-fn)以外的任何参数,则gulp将退出运行:
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的退出代码会导致gulp过早退出。将它包装在函数中意味着仍然调用done
但没有任何参数 - 导致正常完成。
答案 1 :(得分:1)
马克,
有几件事。
我有完全相同的问题,了解gulp对回调做了什么以及它是如何工作的。首先,我们必须了解gulp允许您使用两种语法。从task任务函数和gulp返回的一个可以继续执行后续任务,另一个必须为同一目的提供回调。这些是等价的:
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();
});
已完成被定义为 {} 花括号内的任何内容。 逗号。但是gulp任务需要执行一个函数。好的,执行的函数是get_karma_server的执行,它返回服务器的实例和 .start()
如果这不能让你呕吐我不知道是什么。
这就是为什么它不起作用
如果你没有执行该功能,那么你就没有服务器的实例,这意味着start不是undefined的功能,这意味着gulp没有得到它的回调。因此所有与回调相关的错误。
第2步
function get_karma_server(){
return new KarmaServer({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}
}
gulp.task('test', function(done){
get_karma_server().start();
});
仍然相同,但现在它更有意义。 已完成仍然是gulp的回调。
第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);
});
请详细说明。它在运行时并不慢,而且理解起来要快得多。
--------------编辑--------------
@Mark,我道歉。我理解这个问题,但没有传达信息。这不是ES5与ES6的关系。
括号()语法用于执行,对吗?你可以执行一些不是函数的东西,但是javascript会尝试执行它,但是会给出错误而不是错误。
在这种情况下,您可以通过名称提供带有函数的业力,比如x,然后业力将通过x()获取x和call()。对?这是因为它希望x在处理完测试后成为一个函数。因此回叫。
现在,在x javascript中将执行所有内容,就像常规函数一样,然后它会遇到这个完成的事情,它不知道如何处理它因为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中使用完成:
function x(){
// get things done here
// and...
done; // Get ready for some errors
}
在这里使用完成就可以了。
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.
}
我希望这更有意义。我讨厌它,因为我的语气不连贯,而且这个帖子比预期的要长。