循环中的节点Grunt异步任务,关闭不起作用

时间:2013-01-18 21:26:21

标签: node.js asynchronous callback closures gruntjs

提前感谢您看一下。

我在一个无效的循环中有一个异步任务。我已经确定:

  1. 将我的循环变量“key”包装在一个闭包中以避免经典的“最后一个值” 只有“问题,在异步任务返回值之前循环完成的时间很长,只显示最后一个值。
  2. 调用完成(错误)以完成我的异步任务(根据Gruntjs常见问题解答)
  3. 使用hasOwnProperty()确保密钥是对象的实际属性,而不是来自原型。
  4. 遵循node.exec示例的格式,除了将exec的值赋给变量 - 我已尝试过,但它没有帮助。见下面的第一个参考文献。
  5. 此功能输出......没有!?由于某种原因,grunt.log.writeln语句甚至没有触发。任务完成且没有错误。我还尝试添加一个20秒的延迟,以防脚本在异步任务返回之前完成。奇怪的是,如果我不调用“done(error)”,文件将写入文件(当我用grunt.file.write语句替换writeln时)。

    var done = this.async(),
        exec = require('child_process').exec,
        myJSON = {
          "file1" : "C:/home/me/jquery.js",
          "file2 " : "C:/home/me/grunt.js",
          ...
          "fileN" : "C:/home/me/N.js"
        },
        count;
    
    for (var key in myJSON) {
        if (myJSON.hasOwnProperty(key)) {
          (function (key) { 
            exec( 'type "' + myJSON[key] + '"', 
              function(error, stdout, stderr) {
                if (error) {
                    grunt.log.writeln('!!! exec error: ' + error);
                }
                grunt.log.writeln('stdout: ' + stdout);
                grunt.log.writeln('stderr: ' + stderr);
                done(error);
              }
            );
          })(key);
        count++;
      }
    }
    

    参考文献:

    http://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback https://github.com/gruntjs/grunt/wiki/Frequently-Asked-Questions

1 个答案:

答案 0 :(得分:13)

只有在整个操作完成时才会调用

done(),这意味着所有exec()方法都运行了它们的回调。目前,您正在每次迭代时执行done回调。您可以使用grunt附带的节点模块async中的forEach方法轻松实现此目的(grunt.util.async(或forEachSeries,如果您需要exec()按顺序执行的方法。

像这样(未经测试):

var done = this.async();
var exec = require('child_process').exec;
var async = grunt.util.async; // updated
var myJSON = {
  "file1": "C:/home/me/jquery.js",
  "file2": "C:/home/me/grunt.js",
  ...
  "fileN": "C:/home/me/N.js"
};

async.forEach(Object.keys(myJSON), function(el, cb) {
  exec('type "' + myJSON[el] + '"', function(error, stdout, stderr) {
      if (error) {
          grunt.warn('!!! exec error: ' + error)
          return cb(error);
      }
      grunt.log.writeln('stdout: ' + stdout);
      grunt.log.writeln('stderr: ' + stderr);
      cb();
    }
  );
}, function(error) {
  done(!error);
});