在子任务完成后将 g运行t 运行 设为任务
Make grunt run a task after subtask is done
问题
我有一个 g运行t 任务来启动自动化测试。逻辑如下:
清理.tmp
文件夹->找到需要的.xlx格式的数据文件->转换.tmp
文件夹下JSON中的文件->开始对转换后的文件进行测试
它工作正常,直到数据文件变得非常大,并且在转换文件的子任务完成之前开始测试
问题
如何让 g运行t 等到子任务完成,不 more/no 少?
到目前为止我尝试了什么
我尝试了几种方法使 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();
});
在创建数据文件之前,它仍然会尝试 运行 量角器
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 秒,没有做任何事情,甚至在数据转换开始之前。所以从日志中我看到 - g运行t started -> hang 2000 -> convert -> 运行 protractor
我建议你需要的是拥有信号量变量
https://en.m.wikipedia.org/wiki/Semaphore_(programming)
在这种情况下,创建名为 dataLoaded
的全局变量并将其设置为 false
。
在您的第一个子任务完成后将其设置为 true
。
您的第二个任务可以在启动时检查 dataLoaded
的值,如果它未设置为 true
,请自行调用 setTimeout
稍等片刻,然后重试.
function foo() {
if (!dataLoaded) {
setTimeout(foo, 50)
return
}
...
}
解决方案
// 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
模块可以选择传递我所做的回调函数。所以我需要做的就是在最后一个 sheet 的标签转换实际完成时调用 done()
。
修复后我遇到的唯一问题是这个错误 Fatal error: ENOENT: no such file or directory, mkdir ...
,只需将 mkdir
引入游戏就可以解决
重要
它仍然不理想,因为如果我的 excel 文件中有 10 个 sheet,第五个是最大的,但我只等最后一个,它不会工作。但只要我知道如何修复它,我就会在需要时这样做
问题
我有一个 g运行t 任务来启动自动化测试。逻辑如下:
清理.tmp
文件夹->找到需要的.xlx格式的数据文件->转换.tmp
文件夹下JSON中的文件->开始对转换后的文件进行测试
它工作正常,直到数据文件变得非常大,并且在转换文件的子任务完成之前开始测试
问题
如何让 g运行t 等到子任务完成,不 more/no 少?
到目前为止我尝试了什么
我尝试了几种方法使 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();
});
在创建数据文件之前,它仍然会尝试 运行 量角器
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 秒,没有做任何事情,甚至在数据转换开始之前。所以从日志中我看到 - g运行t started -> hang 2000 -> convert -> 运行 protractor
我建议你需要的是拥有信号量变量
https://en.m.wikipedia.org/wiki/Semaphore_(programming)
在这种情况下,创建名为 dataLoaded
的全局变量并将其设置为 false
。
在您的第一个子任务完成后将其设置为 true
。
您的第二个任务可以在启动时检查 dataLoaded
的值,如果它未设置为 true
,请自行调用 setTimeout
稍等片刻,然后重试.
function foo() {
if (!dataLoaded) {
setTimeout(foo, 50)
return
}
...
}
解决方案
// 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
模块可以选择传递我所做的回调函数。所以我需要做的就是在最后一个 sheet 的标签转换实际完成时调用 done()
。
修复后我遇到的唯一问题是这个错误 Fatal error: ENOENT: no such file or directory, mkdir ...
,只需将 mkdir
引入游戏就可以解决
重要
它仍然不理想,因为如果我的 excel 文件中有 10 个 sheet,第五个是最大的,但我只等最后一个,它不会工作。但只要我知道如何修复它,我就会在需要时这样做