为什么在将"done"功能传递给Karma的服务器时gulp会出错?



(到目前为止)只写了一个非常简单的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被传递给除nullundefined之外的任何参数,则该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.
}

我希望这更有意义。我讨厌我语无伦次,而且这篇文章的篇幅比预期的要长

最新更新