如何解决在执行gulp任务中出现的错误ReferenceError: primordials is not defined

  • A+
所属分类:Web前端
摘要

  最近在执行一个gulp任务时遇到下面这个错误:  Google的结果是说这个是gulp 3在Node 12.x上的一个bug。解决的办法有两个:要么通过nvm将node版本降到12以下,要么将gulp升级到4。由于我工作的电脑上还有其它的项目需要依赖node 12.x版本,所以只能采用第二种办法,将gulp升级到4.0.2。升级完之后继续执行刚才的命令,然后问题又来了:

  最近在执行一个gulp任务时遇到下面这个错误:

如何解决在执行gulp任务中出现的错误ReferenceError: primordials is not defined

  Google的结果是说这个是gulp 3在Node 12.x上的一个bug。解决的办法有两个:要么通过nvm将node版本降到12以下,要么将gulp升级到4。由于我工作的电脑上还有其它的项目需要依赖node 12.x版本,所以只能采用第二种办法,将gulp升级到4.0.2。升级完之后继续执行刚才的命令,然后问题又来了:

如何解决在执行gulp任务中出现的错误ReferenceError: primordials is not defined

  按照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的官方文档的描述,有以下六种解决办法

  1. 返回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任务中存在多个异步操作,则该解决办法也不适用,继续往下看。

  2. 返回一个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中存在多个异步操作,这个解决办法更加适用。

  3. 调用回调函数
    这个解决办法可能是最容易的。由于gulp会自动将回调函数作为第一个参数传递进来,所以当任务执行完后,你可以显式地执行这个回调函数:
    gulp.task('message', function(done) {   console.log("HTTP Server Started");   done(); }); 

  4. 返回一个子进程
    不太推荐这个解决办法,因为它可能会过度依赖于系统环境。但是如果你可以在代码中直接调用命令行工具,这个解决办法可能会有用。
    var spawn = require('child_process').spawn;  gulp.task('message', function() {   return spawn('echo', ['HTTP', 'Server', 'Started'], { stdio: 'inherit' }); });

  5. 返回一个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; });

  6. 返回一个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; });