最近在執行一個gulp任務時遇到下面這個錯誤:

Google的結果是說這個是gulp 3在Node 12.x上的一個bug,解決的辦法有兩個:要么通過nvm將node版本降到12以下,要么將gulp升級到4,由于我作業的電腦上還有其它的專案需要依賴node 12.x版本,所以只能采用第二種辦法,將gulp升級到4.0.2,升級完之后繼續執行剛才的命令,然后問題又來了:

按照console中的錯誤描述:Did you forget to signal async completion? 意思是說這個gulp任務有可能是個異步操作,需要標記為async,然后我修改了gulp.js檔案,在對應的task的回呼函式前加了async標記,重新執行命令,順利通過!
gulp.task('makeNodeModule', async () => {
var destPath = "./out";
gulp.src("./lib/**", { 'dot': true })
.pipe(gulp.dest(destPath + "/lib", {'overwrite':true}));
gulp.src("./res/**", { 'dot': true })
.pipe(gulp.dest(destPath + "/res", {'overwrite':true}));
gulp.src("./package.json")
.pipe(gulp.dest(destPath, {'overwrite':true}));
});
這是由于在gulp的任務中包含了異步代碼,你必須在任務執行完后告訴gulp(異步操作),在gulp 3.x中可以不用處理,如果沒有顯式地進行async標記,gulp會假定任務是同步執行的,一旦函式回傳結果,gulp的任務也就結束了,但是gulp 4在這方面要求更加嚴格,你必須明確告知gulp任務何時執行完畢,事實上,按照gulp的官方檔案的描述,有以下六種解決辦法:
- 回傳Stream
如果gulp任務只是在控制臺輸出一些資訊,這個解決辦法可能并不適用,不過在大多數情況下我們都會使用gulp streams來完成一個異步操作,下面是一個例子:
var print = require('gulp-print'); gulp.task('message', function() { return gulp.src('package.json') .pipe(print(function() { return 'HTTP Server Started'; })); });
這里的return陳述句是關鍵,如果不回傳stream,gulp就不會知道該任務何時結束,當然,如果一個gulp任務中存在多個異步操作,則該解決辦法也不適用,繼續往下看,
- 回傳一個Promise
在大多數情況下,這個解決辦法可能更適用,不過在真實使用場景下,你可能并不需要自己創建一個Promise物件,我們可以借助于第三方的包來構建一個Promise(例如使用del包),
gulp.task('message', function() { return new Promise(function(resolve, reject) { console.log("HTTP Server Started"); resolve(); }); });使用async/await語法可以進一步簡化上面的代碼,所有標記為async的函式都會隱式地回傳一個Promise,所以上面的代碼也可以改成下面這種形式(前提是你使用的node版本要支持):
gulp.task('message', async function() { console.log("HTTP Server Started"); });顯然,如果一個gulp中存在多個異步操作,這個解決辦法更加適用,
- 呼叫回呼函式
這個解決辦法可能是最容易的,由于gulp會自動將回呼函式作為第一個引數傳遞進來,所以當任務執行完后,你可以顯式地執行這個回呼函式:
gulp.task('message', function(done) { console.log("HTTP Server Started"); done(); }); - 回傳一個子行程
不太推薦這個解決辦法,因為它可能會過度依賴于系統環境,但是如果你可以在代碼中直接呼叫命令列工具,這個解決辦法可能會有用,
var spawn = require('child_process').spawn; gulp.task('message', function() { return spawn('echo', ['HTTP', 'Server', 'Started'], { stdio: 'inherit' }); });
- 回傳一個RxJS Observable
如果你使用RxJS,這個解決辦法可能會適用,
var of = require('rxjs').of; gulp.task('message', function() { var o = of('HTTP Server Started'); o.subscribe(function(msg) { console.log(msg); }); return o; });
- 回傳一個EventEmitter
和前一個一樣,真實場景下你可能不太會使用這個解決辦法,不過如果你已經在代碼中使用了EventEmitter,這個解決辦法可能會有用,
gulp.task('message3', function() { var e = new EventEmitter(); e.on('msg', function(msg) { console.log(msg); }); setTimeout(() => { e.emit('msg', 'HTTP Server Started'); e.emit('finish'); }); return e; });
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/276600.html
標籤:JavaScript
下一篇:初學 Babel 作業原理
