Grunt Plugin- async.each with globbing pattern

时间:2014-07-24 13:45:40

标签: javascript node.js asynchronous gruntjs npm

我正在处理一个由其他人编写的grunt插件来接收硬编码的文件名(src和dest),但是我试图将其更改为能够被指向到具有通配模式的目录,并为" dest"指定输出文件夹。但是我遇到了async.each的问题,因为我的初始实现有一个嵌套的async.each。具体来说,我认为我在何时调用callback()时遇到问题。我在某个地方的某个循环中被挂断了。

这确实可以正常工作,因为文件是通过配置Gruntfile.js的两种方式正确创建的,但之前正在运行的测试现在已经破解。

我只想知道如何构建第二个嵌套循环。也许这不需要使用异步?

Gruntfile.js应该能够配置为:

myplugin: {
    dev: {
        files : {
            'src/business.html': 'src/test_src/business.test',
            ...
        }
    }
},

或作为一种通配模式(这是我正在添加的)

myplugin: {
    dev: {
        src: ['src/test_src/*.test'],
        dest: 'output'
    }
},

该插件以一个async.each开始,每个循环处理一个特定的"文件"源/目标。但是当我们使用globbing模式时,只有一个外部循环,即模式,所以我需要第二个async.each来处理实际文件(有~11个)。

grunt.registerMultiTask('myplugin', 'Compiles files using myplugin', function () {

    done = this.async();

    // Iterate over all specified file groups.
    async.each(this.files, function (fileGlob, cb) {
        var destination = fileGlob.dest;
        grunt.log.debug("FileGlob: " + fileGlob);

        async.each(fileGlob.src, function (filepath, callback) {
            if (notAPartial(filepath) && grunt.file.exists(filepath)) {
                if (filepath.match(/\.(test|html)$/)) {
                    grunt.log.debug('test compilation of ' + filepath);
                    compileMyFile(filepath, destination);
                } else {
                    // this callback is from the orig version
                    // i think it's causing problems with the nested async.each calls
                    callback(new Error("No handler for filetype: " + filepath));
                }
            }
        }, function(err) {
            if(err) done(err);
            else done();
        });
        cb();
    }, function(err) {
        if(err) done(err);
        else done();
        grunt.log.ok("Compiled " + count + " files.");
    });
})

1 个答案:

答案 0 :(得分:0)

看起来你的回调有点不合适。 async.each的签名为:async.each(arrayOfThings, callbackPerThing, callbackWhenWeGotThroughAllThings)

对于嵌套async.each语句,我喜欢根据它们的作用来命名回调,以避免在嵌套时出现混淆,例如:

var done = this.async();
async.each(this.files, function(fileGlob, nextGlob) {
  async.each(fileGlob.src, function(filepath, nextFile) {
    doSomethingAsync(function() {
      // Continue to the next file
      nextFile();
    });
  }, function() {
    // When we are done with all files in this glob
    // continue to the next glob
    nextGlob();
  });
}, function() {
  // When we are done with all globs
  // call done to tell the Grunt task we are done
  done();
});

在上面的情况中,你是对的,不需要内在的async.each。您也不需要外部async.each,因为没有任何操作看起来是异步的。您可以更简单地执行以下操作:

grunt.registerMultiTask('myplugin', 'Compiles files using myplugin', function () {
  this.files.forEach(function(fileGlob) {
    var destination = fileGlob.dest;
    grunt.log.debug("FileGlob: " + fileGlob);

    fileGlob.src.forEach(function(filepath) {
      if (notAPartial(filepath) && grunt.file.exists(filepath)) {
        if (filepath.match(/\.(test|html)$/)) {
          grunt.log.debug('test compilation of ' + filepath);
          compileMyFile(filepath, destination);
         } else {
           grunt.log.error("No handler for filetype: " + filepath);
         }
       }
    });
  });

  grunt.log.ok("Compiled " + count + " files.");
});