是否有更好的方法使用Node.js运行CLI命令?
我刚刚写了一个脚本来发布我正在开发的一个产品的构建。脚本完成了这项工作,但我并不真正喜欢代码本身,它看起来像意大利面条代码和回调地狱的结合 有没有更干净的方法?我希望能够连续运行命令、记录输出(是否有更好的方法使用Node.js运行CLI命令?,node.js,command-line-interface,Node.js,Command Line Interface,我刚刚写了一个脚本来发布我正在开发的一个产品的构建。脚本完成了这项工作,但我并不真正喜欢代码本身,它看起来像意大利面条代码和回调地狱的结合 有没有更干净的方法?我希望能够连续运行命令、记录输出(stdout.on('data'))以及任务完成时。(便于进一步调试,在等待任务完成时,可以放心地知道后台发生了什么) 也许使用承诺会有助于清理混乱,但我仍然觉得应该有一种更干净的方法来处理多个命令 有关代码功能的一些说明: 创建一个具有所需提交和所需标记版本的标记,即:git-tag 1.2.5 使用
stdout.on('data')
)以及任务完成时。(便于进一步调试,在等待任务完成时,可以放心地知道后台发生了什么)
也许使用承诺会有助于清理混乱,但我仍然觉得应该有一种更干净的方法来处理多个命令
有关代码功能的一些说明:
git-tag 1.2.5
gulpbuild
构建发布文件doc/
doc/doc\u reader.odt
转换为doc//documentation.pdf
。(打开并导出为PDF)build/reader.js
和doc/changelog.txt
版本1.2.11
(例如)下面是代码,作为示例。(ES5,节点4.6.0+)
编辑: 下面是使用async/await(节点7.8.0)的实现 我使用了特殊的
mkdirp
和exec
模块,允许与wait
一起使用。但是我找不到spawn
的等价物
const mkdirp = require('async-mkdirp');
const fs = require('fs-extra');
const spawn = require('child-process-promise').spawn;
const exec = require('mz/child_process').exec;
const zip = new require('node-zip')();
const c = require('chalk');
const error = c.bold.red;
const warn = c.yellow;
const info = c.cyan;
const info2 = c.magenta;
const version = require('../package.json').version;
const releaseDirectory = 'doc'
async function git_tag() {
async function exec_git_tag() {
return await exec(`git tag ${version}`);
}
console.log(info(`Creating git tag ${version}`));
return exec_git_tag()
.then(() => {
console.log(info(`Git tag created for ${version}`))
})
.catch((err) => {
console.log(warn('warn', err));
})
// Finally
.then(() => {
console.log(info(`"git tag ${version}" - Completed`))
});
};
async function gulp_build() {
async function exec_gulp_build() {
const promise = spawn('gulp', ['build'])
const childProcess = promise.childProcess;
childProcess.stdout.on('data', (data) => {
console.log(info2(data.toString()));
});
childProcess.stderr.on('data', (data) => {
console.log(error(data.toString()));
});
return promise
.catch((err) => {
console.error(error(err));
})
// Finally
.then(() => {
console.log(info('"gulp build" - Completed'))
});
}
console.log(info('Running "gulp build"...'))
return exec_gulp_build()
}
async function create_dir() {
const dirPath = `${releaseDirectory}/${version}`;
console.log(info(`Creating "${dirPath}" directory.`))
await mkdirp(`${dirPath}`);
console.log(info(`Directory ${dirPath} created.`));
}
async function build_doc() {
const docFile = `${releaseDirectory}/doc_reader.md`;
console.log(info(`Converting ${docFile} to pdf ...`));
async function exec_build_doc() {
return await exec(`npm run build:doc`);
}
return exec_build_doc()
.catch((err) => {
console.error(error(err));
})
.then(() => {
console.log(info(`Doc "${docFile}" created.`));
})
}
function copy_files() {
console.log(info('Copying changelog.txt ...'));
fs.copySync('doc/changelog.txt', `doc/${version}/changelog.txt`);
console.log(info('changelog.txt copied.'));
console.log(info(`Copying "build/reader.js" to "doc/reader-${version}.js" and "doc/reader.js" ...`));
fs.copySync('build/reader.js', `doc/${version}/reader.js`);
fs.copySync('build/reader.js', `doc/${version}/reader-${version}.js`);
console.log(info('reader.js copied.'));
}
function zip_files() {
console.log(info('Zipping all files ...'));
zip.file('changelog.txt', fs.readFileSync(`doc/${version}/changelog.txt`));
zip.file('doc_reader.pdf', fs.readFileSync(`doc/${version}/doc_reader.pdf`));
zip.file('reader.js', fs.readFileSync(`doc/${version}/reader.js`));
zip.file(`reader-${version}.js`, fs.readFileSync(`doc/${version}/reader-${version}.js`));
const data = zip.generate({ base64: false, compression: 'DEFLATE' });
const zipFilename = `doc/${version}/HTML5Reader_${version}.zip`;
fs.writeFileSync(zipFilename, data, 'binary'); // it's important to use *binary* encode
console.log(info(`${zipFilename} created.`));
}
async function release() {
await git_tag();
await gulp_build();
await create_dir();
await build_doc();
copy_files();
zip_files();
console.log(`\nRelease ${version} done. Please add generated files and commit using:`);
console.log(`\n\tgit add . && git commit -m "Release ${version}"`);
}
release();
这里有一个非常有用的
mz
模块。见:
async
/await
相结合,将允许您编写如下代码:
let exec = require('mz/child_process').exec;
(async () => {
let version = await exec('node --version');
console.log(version);
let result = await exec('some other command');
console.log(result);
// ...
})();
这是一个简单的示例,但您可以通过这种方式使用child\u进程
、fs
和许多其他模块中的所有函数
这里重要的是,此代码仍然是异步的和非阻塞的
请注意,您只能在使用async
关键字创建的函数中使用wait
。有关详细信息,请参阅:
async
和wait
的地方,可以使用Babel:
co
或Bluebird协同程序:
spawn
tho。
let exec = require('mz/child_process').exec;
(async () => {
let version = await exec('node --version');
console.log(version);
let result = await exec('some other command');
console.log(result);
// ...
})();