我想从Gulp运行几个SQL脚本:
const gulp = require('gulp');
const dotenv = require('dotenv')
const child_process = require('child_process');
function runSQLScript(script) {
child_process.execFile('sqlcmd', [
'-S', process.env.DB_SERVER,
'-U', process.env.DB_USER,
'-P', process.env.DB_PASSWORD,
'-d', process.env.DB_DATABASE,
'-f', 'i:65001',
'-i', script
], {
cwd: '../sql/sqlcmd'
}, function(error, stdout, stderr){
if (error !== null) {
console.log("" + stdout);
console.error("" + error);
}
if (stderr.length>0) {
console.error('' + stderr);
}
});
}
gulp.task('sql', ['install-app', 'load-data']);
gulp.task('install-app', function(){
runSQLScript('install-app.sql');
});
gulp.task('load-data', function(){
runSQLScript('load-data.sql');
});
然后我跑:
gulp sql
在早期版本中,我使用的是child_process.execFileSync()
,我的脚本按预期顺序运行。我切换到child_process.execFile()
以便能够报告错误,但现在load-data.sql
失败了,因为它不再等待install-app.sql
完成。
我可以做什么让任务等到runSQLScript()
完成?我选择了错误的方法来打印错误吗?
答案 0 :(得分:1)
看起来gulp-sequence是最佳选择(如果你的gulp版本是< 4)。
const util = require('util');
const gulp = require('gulp');
const gulpSequence = require('gulp-sequence');
const dotenv = require('dotenv')
const execFile = util.promisify(require('child_process').execFile);
function runSQLScript(script) {
return execFile('sqlcmd', [
'-S', process.env.DB_SERVER,
'-U', process.env.DB_USER,
'-P', process.env.DB_PASSWORD,
'-d', process.env.DB_DATABASE,
'-f', 'i:65001',
'-i', script
], {
cwd: '../sql/sqlcmd'
}, function(error, stdout, stderr){
if (error !== null) {
console.log("" + stdout);
console.error("" + error);
}
if (stderr.length>0) {
console.error('' + stderr);
}
});
}
gulp.task('sql', gulpSequence('install-app', 'load-data'));
gulp.task('install-app', function(){
return runSQLScript('install-app.sql');
});
gulp.task('load-data', function(){
return runSQLScript('load-data.sql');
});
答案 1 :(得分:1)
不幸的是,从.execFileSync()
切换到.execFile()
似乎是在所有情况下捕获脚本输出的最简单方法。出错时,.execFileSync()
不再返回脚本标准输出,并且没有明显的方法来获取它;您可以将其重定向到处理标准输出,但是,如果您需要进一步处理,则存在从那里获取它的问题。虽然冗长和不合逻辑,但异步代码是最不邪恶的。
然后您可以使用gulp-sequence()
作为FrankerZ's answer解释。作为util.promisify()
(需要Node / 8)的替代方法,您还可以使用q使child_process.execFile()
返回承诺。
此外,您似乎需要catch()
runSQLScript()
返回的承诺。否则,无论前一个脚本的结果如何,第二个脚本都会执行。
const gulp = require('gulp');
const dotenv = require('dotenv')
const child_process = require('child_process');
const Q = require('q');
function runSQLScript(script) {
var deferred = Q.defer();
child_process.execFile('sqlcmd', [
'-S', process.env.DB_SERVER,
'-U', process.env.DB_USER,
'-P', process.env.DB_PASSWORD,
'-d', process.env.DB_DATABASE,
'-f', 'i:65001',
'-i', script
], {
cwd: '../sql/sqlcmd'
}, function(error, stdout, stderr){
if (error !== null) {
console.log("" + stdout);
console.error("" + error);
deferred.reject();
} else {
deferred.resolve();
}
if (stderr.length>0) {
console.error('' + stderr);
}
});
return deferred.promise;
}
gulp.task('sql', gulpSequence('install-app', 'load-data'));
gulp.task('install-app', function(callback){
runSQLScript('install-app.sql')
.then(function(){
callback();
})
.catch(function(){
callback("install-app failed, aborting");
});
});
gulp.task('load-data', function(callback){
runSQLScript('load-data.sql')
.then(function(){
callback();
})
.catch(function(){
callback("load-data failed, aborting");
});
});