【问题标题】:gulp watchers and promises result in crashgulp 观察者和承诺导致崩溃
【发布时间】:2015-10-08 14:32:26
【问题描述】:

我正在尝试 Gulp,我设置了一个任务来监视我的 .js 文件,以便在修改它们时运行我的测试并检查我的代码。

但是,自从我开始在我的代码中使用 Promise 后,watch 任务就中断了。我第一次修改监视文件时它会运行良好,但之后每次都会崩溃:

Message:
    Object.keys called on non-object
Stack:
TypeError: Object.keys called on non-object
    at Function.keys (native)
    at processExports (/Users/hfp/code/coverall/node_modules/nodegit/node_modules/promisify-node/index.js:44:16)
    at module.exports (/Users/hfp/code/coverall/node_modules/nodegit/node_modules/promisify-node/index.js:112:10)
    at Object.<anonymous> (/Users/hfp/code/coverall/node_modules/nodegit/lib/nodegit.js:96:26)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/Users/hfp/code/coverall/lib/archive.js:10:13)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/Users/hfp/code/coverall/test/archive_spec.js:6:15)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)

这是我完整的 Gulpfile,我使用 gulp dev 运行监视任务:

var gulp = require('gulp');
var mocha = require('gulp-mocha');
var gutil = require('gulp-util');
var eslint = require('gulp-eslint');
var console = require('better-console');
var runSequence = require('run-sequence');
var istanbul = require('gulp-istanbul');
var insert = require('gulp-insert');

var spec_files = 'test/**/*_spec.js';
var integration_files = 'test/**/*_integration.js';
var code_files = ['lib/**/*.js', 'helpers/**/*.js', 'index.js'];
var all_files = code_files.concat(spec_files, integration_files);
var coverage_report_dir = 'test/coverage';
var mocha_reporter = 'list';
var eslint_mocha_header = '/*eslint-env mocha */\n';

gulp.task('mocha', function() {
  return gulp.src(spec_files, { read: false })
    .pipe(mocha({ reporter: mocha_reporter }));
});

gulp.task('cov', function(cb) {
  return gulp.src(code_files)
    .pipe(istanbul({ includeUntested: true }))
    .pipe(istanbul.hookRequire())
    .on('finish', function () {
      gulp.src([spec_files, integration_files])
        .pipe(mocha({ reporter: 'dot' }))
        .on('error', function(err) {
          console.log('Error in tests, not checking coverage.');
          cb(err);
        })
        .pipe(istanbul.writeReports( { reporters: ['html', 'text', 'text-summary'] }))
        .on('end', cb);
    });
});

gulp.task('dev', function() {
  return gulp.watch(all_files, ['test'], { read: false });
});

gulp.task('lint', ['eslint-add-mocha-headers'], function(cb) {
  return gulp.src(all_files)
    .pipe(eslint({ useEslintrc: true }))
    .pipe(eslint.format())
    cb(err);
});

gulp.task('clear-console', function() {
  return console.clear();
});

gulp.task('eslint-add-mocha-headers', function(cb) {
  var truncated_header = eslint_mocha_header.substring(0, eslint_mocha_header.length - 1);
  // turn the header into a regex so if I update the header, this task doesn't break
  var header_regex = new RegExp('^' + truncated_header.replace(/\*/gi, '\\*').replace(/\//gi, '\\/'));

  return gulp.src(spec_files)
    .pipe(insert.transform(function(contents, file) {
      if (contents.match(header_regex)) {
        return contents;
      }
      return eslint_mocha_header + contents;
    }))
    .pipe(gulp.dest('test/'));
});

gulp.task('test', function(cb) {
  return runSequence('clear-console',
              'lint',
              'mocha',
              cb);
});

【问题讨论】:

    标签: javascript node.js gulp gulp-watch


    【解决方案1】:

    我也遇到过同样的问题,但解决方案因不同情况而异。这 3 个中的一个通常会为我修复它:

    1) 切换到运行序列的非回调语法。例如:

    gulp.task('test', function(){ 
        return runSequence('clear-console', 'lint', 'mocha'); 
    });
    

    2) 尝试在 runSequence 中定义 eslint-add-mocha-headers 'sequential' 依赖项,而不是用两种不同的方式定义所需的运行顺序。这在过去的某些情况下为我解决了这个问题。 (无论如何它更具可读性)。例如:

    gulp.task('test', function(){ 
        return runSequence('eslint-add-mocha-headers', 'clear-console', 'lint', 'mocha'); 
    });
    

    3) 这是你最好的选择:尽量不要返回 gulp.watch。 gulp watch 讨厌被退回:在大多数情况下,我的结果是重复地将更多的观察者分配给相同的文件,每次对文件进行更改时,观察者的数量都会增加。这通常会使运行 Gulp 的 Node 进程崩溃(由于内存耗尽、文件锁冲突和/或分配的观察者数量超过了进程支持的数量)。例如:

    gulp.task('dev', function() {
        gulp.watch(all_files, ['test'], { read: false });
    });
    

    错误发生在哪一行代码上?你有没有得到堆栈跟踪?

    【讨论】:

    • 谢谢。如果我删除回调,则各种任务会相互交叉,并且在任务中途重新启动时我不会获得完整的输出。我不能没有回调。我删除了退货,但没有任何区别。 stacktrace 指向 promisify 和 nodegit 模块。我已将跟踪添加到我的问题中。
    • 您是否可以使用 Bluebird(如果可能)而不是 Promisify?这可能会解决您的问题 - Bluebird 是一个更强大的模块,具有更少的陷阱。另一方面,您是否尝试在 Object.keys 调用之前直接输出有问题的变量的内容?即 console.log(offendingVariableName)。另外,上面跟踪中的哪些文件是你的(相对于原生 Node 包或 npm 模块)?
    • 我在自己的代码中使用 Bluebird,但 nodegit 模块似乎使用 promisify 而不是 bluebird。我在这里无能为力,不幸的是,这不是我的模块。我只拥有跟踪中提到的文件中的lib/archive.jstest/archive_spec.js
    • 嗯...介意在堆栈跟踪中的每个位置发布代码吗?这看起来像一个异步错误,其中运行 Object.keys 的变量是一个对象,如果回调已返回(或承诺已解决或其他),但如果没有,则未定义。一种竞争条件,其中代码依赖于一段异步执行的代码才能完成运行。
    • (这也很有意义,因为在第一次学习使用 Promise 时很容易犯错误)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多