使用Commander.js时全局选项在子命令前执行顺序异常问题
解决Commander.js全局参数与子命令执行顺序问题
我懂你遇到的这个困扰——明明把全局参数--hello放在子命令前面,结果子命令的输出反而先跑出来了,完全和预期顺序反过来了对吧?
问题根源
这是Commander.js的默认执行逻辑导致的:当调用program.parse(process.argv)时,程序会优先识别并执行子命令的action回调函数,等子命令的逻辑跑完之后,才会去处理你写在parse之后的全局参数判断代码,所以输出顺序自然就和你预期的相反了。
解决方案
要让全局参数的逻辑先执行,你可以用Commander.js提供的**preAction钩子**,这个钩子会在所有子命令的action执行前触发,刚好匹配你的需求。
修改后的代码如下:
const { program } = require('commander'); program .version('0.0.1','-V, --version') .option('-h, --hello','print hello') program .command('msg') .option('-w, --world','print world') .action(function(options){ console.log("inside subcommand"); if(options.world){ console.log("world"); } }); // 新增preAction钩子,在子命令action前执行全局参数逻辑 program.hook('preAction', (thisCommand) => { if (thisCommand.parent.hello) { // 通过parent获取全局参数 console.log("hello"); } }); program.parse(process.argv);
验证效果
当你执行命令node your-file.js --hello msg --world时,输出就会和你预期的完全一致:
hello inside subcommand world
补充思路
如果不想用钩子,也可以把全局参数的处理逻辑封装成函数,在每个子命令的action开头先调用这个函数,但这种方式在多子命令场景下会重复代码,远不如钩子来得优雅。
内容的提问来源于stack exchange,提问作者Shivam Kumar




