将“done”函数传递给Karma的服务器时为什么会出现gulp错误?

时间:2016-05-31 16:54:25

标签: javascript node.js gulp karma-runner

只写一个(到目前为止)非常简单的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

2 个答案:

答案 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传递除nullundefinedhttps://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.
}

我希望这更有意义。我讨厌它,因为我的语气不连贯,而且这个帖子比预期的要长。