让Grunt在子任务完成后运行一个任务

4

问题

我有一个grunt任务来启动自动化测试。逻辑如下:

清理.tmp文件夹 -> 在.xlx格式中查找所需的数据文件 -> 将文件转换为位于.tmp文件夹下的JSON格式 -> 开始针对已转换文件进行测试。

它一直工作得很好,直到数据文件变得非常大,而在子任务完成文件转换之前开始测试。

问题

如何使grunt等待子任务完成,不多不少?

我到目前为止尝试过的方法

我已经尝试过几种使convert-data-sheet任务异步的方法,但都没有成功。

1. 显然,我尝试的第一件事情是这个:

// register task for converting data sheet
grunt.registerTask('convert-data-sheet', 'task for converting xslx file into json', function(product, tenant, environment, codeBase) {
    
   let done = this.async();
   /*
    Some code here, not essential to the question
    */
    // run conversion for each sheet
    for (let i = 0; i < sheetTabs.length; i++) {
        dst = path.resolve(__dirname, './protractor/.tmp_files/test_data', `${sheetTabs[i]}.json`);
        options.sheet = (i + 1).toString();
        convertExcel(src, dst, options);
    }
    done();
});

// register a task for ui tests
grunt.registerTask('e2e', 'task for protractor tests', function() {
    let done = this.async();
    grunt.initConfig({
        /**
         * Long and boring initConfig object
         */
    });

    // clean .tmp directory
    grunt.task.run('clean:tmpFiles');

    // generate data json files and other files
    grunt.task.run([`convert-data-sheet:${parameters.product}:${parameters.tenant}:${parameters.environment}:${parameters.codeBase}`, 'bake:protractorConfigs']);

    grunt.task.run('protractor:configFile');
    done();
});


1. 在数据文件创建之前,它仍然尝试运行Protractor。
2. 这里是我的当前代码,在指定的时间段内一直挂起。
// register task for converting data sheet
grunt.registerTask('convert-data-sheet', 'task for converting xslx file into json', function(product, tenant, environment, codeBase) {
    /*
    Some code here, not essential to the question
    */
    // run conversion for each sheet
    for (let i = 0; i < sheetTabs.length; i++) {
        dst = path.resolve(__dirname, './protractor/.tmp_files/test_data', `${sheetTabs[i]}.json`);
        options.sheet = (i + 1).toString();
        convertExcel(src, dst, options);
    }
});

// register a task for ui tests
grunt.registerTask('e2e', 'task for protractor tests', function() {

    let done = this.async();

    grunt.initConfig({
        /**
         * Long and boring initConfig object
         */
    });

    // clean .tmp directory
    grunt.task.run('clean:tmpFiles');

    // generate data json files and other files
    grunt.task.run([`convert-data-sheet:${parameters.product}:${parameters.tenant}:${parameters.environment}:${parameters.codeBase}`, 'bake:protractorConfigs']);

    // run protractor with a delay 2000ms to let previous tasks finish
    setTimeout(function() {
        grunt.task.run('protractor:configFile');
        done();
    }, 2000);
});

但事实证明,即使当前代码也没有做到预期的功能。甚至在数据转换开始之前,它只是挂起了2秒钟而没有做任何事情。因此,从日志中我看到 - grunt started -> hang 2000 -> convert -> run protractor。

2个回答

3

解决方案

// register task for converting data sheet
grunt.registerTask('convert-data-sheet', 'task for converting xslx file into json', function(product, tenant, environment, codeBase) {

   let done = this.async();
   /*
    Some code here, not essential to the question
    */
    mkdirp(path.resolve(__dirname, './protractor/.tmp_files/test_data'), function(err) {

        // run conversion for each sheet
        for (let i = 0; i < sheetTabs.length; i++) {
            dst = path.resolve(__dirname, './protractor/.tmp_files/test_data', `${sheetTabs[i]}.json`);
            options.sheet = (i + 1).toString();
            convertExcel(src, dst, options,
                (err, data) => {
                    if (i === (sheetTabs.length - 1)) {
                        done();
                    }
                }
            );
        }
    });
});

// register a task for ui tests
grunt.registerTask('e2e', 'task for protractor tests', function() {

    grunt.initConfig({
        /**
         * Long and boring initConfig object
         */
    });

    // clean .tmp directory
    grunt.task.run('clean:tmpFiles');

    // generate data json files and other files
    grunt.task.run([`convert-data-sheet:${parameters.product}:${parameters.tenant}:${parameters.environment}:${parameters.codeBase}`, 'bake:protractorConfigs']);

    grunt.task.run('protractor:configFile');

});

这种方法的特点

我不完全理解任务同步执行的情况。

众所周知,这种情况很常见。

console.log(1)
setTimeout(function(){console.log(2)}, 1000)
console.log(3)

导致

1
3
2

因为JS只是安排setTimeout, 在等待1000毫秒的同时继续脚本执行。

在我的情况下,你可以把convertExcel看成是setTimeout。所以JS安排了转换并立即调用done(),所以Grunt没有等到实际完成过程就结束了。

幸运的是,excel-as-json模块有传递回调函数的选项,我使用了这个选项。所以当最后一个工作表被转换完毕时,我只需要调用done()即可。

在修复后我遇到的唯一问题是这个错误:Fatal error: ENOENT: no such file or directory, mkdir...,通过引入mkdir解决了该问题。

重要提示

这仍然不理想,因为如果我的Excel文件中有10个工作表,第五个是最大的,但我只等待最后一个工作表,它不会起作用。但只要我知道如何修复,必要时我会这样做。


1
我建议您需要的是信号量变量。

https://en.m.wikipedia.org/wiki/Semaphore_(programming)

在这种情况下,创建一个名为dataLoaded的全局变量,并将其设置为false
在您的第一个子任务中,一旦完成,将其设置为true
然后,您的第二个任务可以在启动时检查dataLoaded的值,如果它未设置为true,则调用setTimeout以等待一段时间并重试。
function foo() {
  if (!dataLoaded) {
    setTimeout(foo, 50)
    return
  }

  ...
}

好的方法,这三个点代表应该启动测试的代码?还是那段代码应该放在函数外面? - Sergey Pleshakov
开始测试的代码 - David Bradshaw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接