2016-05-31 40 views
3

只寫一個(到目前爲止)非常簡單的gulp文件,我感到困惑的錯誤,我遇到過。爲什麼將`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.053 secs/0.023 secs) 
[17:38:02] Finished 'test' after 2.43 s 

但是當你苗條下來,只是通過done到噶,它失敗而無禮地

​​

...產生:

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

回答

1

馬克,

一些事情。

我有完全相同的問題,瞭解什麼吞嚥與回調和如何一切工作。首先,我們必須明白,吞噬允許你有兩種語法。一個你從任務函數返回的地方可以繼續執行其後的任務,另一個你必須爲同一目的提供回調。這些是等效的:

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(); 
}); 

完成被定義爲無論是內部{}大括號的內容。 逗號。但是一個吞嚥任務需要一個函數來執行。好吧,執行功能是get_karma_server的返回服務器實例和。開始()執行

如果這沒有讓你吐我不知道該怎麼做。

這就是爲什麼它不工作

如果不執行該功能,那麼你沒有服務器,這意味着開始的一個實例是不是未定義的功能,這意味着那吞嚥不能得到它的回調。因此所有的回調相關的錯誤。

步驟2

function get_karma_server(){ 
    return new KarmaServer({ 
     configFile: __dirname + '/karma.conf.js', 
     singleRun: true 
    } 
} 

gulp.task('test', function(done){ 
    get_karma_server().start(); 
}); 

不過相當,但現在看來,有點更有意義。 完成仍然是咕嘟嘟的回調。

步驟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來提供帶有函數的karma,那麼karma將通過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的第一個版本的回調因果報應,這意味着我們必須手動調用來完成:

function x(){ 
    // get things done here 
    // and... 
    done(); // Now gulp can continue because it's callback was called. 
} 

我希望,更有意義。當我語無倫次時,我討厭它,而這篇文章已經超出了它應有的時間。

+0

嗨Wilmer,非常感謝你的詳細解答。不過,我恐怕不管我是否誤解了你的答案,或者你誤解了這個問題。特別是,我認爲可能會對使用es6箭頭函數對'done'做出錯誤的解釋。 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions當我回到我的電腦時,我可以發佈一個沒有箭頭功能的es5版本,這些功能展示了完全相同的特性 - 我只能想象它是一些範圍問題,我還沒有明白... –

+0

在es5中: gulp.task('test',function(done){ new KarmaServer({config | config_file:__dirname +'' /karma.conf.js', singleRun:true },function(){done();})。start(); }); 與 gulp.task( '測試',函數(完成){ 新KarmaServer({ CONFIGFILE:__dirname + '/karma.conf.js', singleRun:真 },完成)。開始( ); }); –

+0

@MarkStickley我作爲編輯添加了答案,因爲它太長了。 –

3

進一步的研究發現,噶解析傳遞給它的退出代碼(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(其它任何說法,一口將退出運行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直接傳遞到嘉rma作爲回調。用函數包裝它意味着done仍然被調用,但沒有任何參數 - 導致正常完成。

+0

這是一個很好的答案。做得好! –

+0

感謝您的幫助,如果沒有您,我不會理解它:) –

相關問題