commander.js中如何在子命令执行前优先处理全局选项?
问题场景
现有如下基于Commander.js编写的脚本:
const {program} = require('commander'); program .option('--foo') .command('bar').action((str, opts) => { console.log('bar!'); }) program.parse(); if (program.opts().foo) { console.log('foo!'); }
执行命令node test.js --foo bar时,实际输出为:
bar! foo!
预期调整执行顺序,实现先输出foo!、后输出bar!的效果。
实现方法
顺序不符合预期的核心原因是Commander的默认执行规则:调用parse()方法时,匹配到子命令后会立即同步执行子命令的action回调,回调执行完成后才会继续运行parse()后续的代码,因此写在parse()后的全局选项判断逻辑会晚于子命令逻辑执行。
你可以根据自己使用的Commander版本选以下任意一种方案实现:
方案1:延迟子命令执行(适用于v9.0.0及以上版本)
开启delayCommandActions配置,让子命令action不在parse阶段自动执行,先处理完全局选项逻辑后,再手动触发子命令运行:const {program} = require('commander'); program .option('--foo') .command('bar').action((str, opts) => { console.log('bar!'); }) // 开启子命令动作延迟执行 program.delayCommandActions = true; program.parse(); // 优先处理全局选项逻辑 if (program.opts().foo) { console.log('foo!'); } // 全局逻辑处理完成后再执行子命令 await program.executeSubCommand();注意:使用该方案时需要将执行逻辑放在async异步函数中,或通过
.then()链式调用处理异步逻辑。方案2:使用preAction钩子处理全局逻辑(全版本兼容)
利用Commander提供的preAction生命周期钩子,该钩子会在所有命令的action执行前触发,把全局选项的处理逻辑放到钩子中即可保证执行顺序:const {program} = require('commander'); program .option('--foo') // 注册执行前钩子,优先处理全局逻辑 .hook('preAction', (currentCommand) => { if (currentCommand.opts().foo) { console.log('foo!'); } }) .command('bar').action((str, opts) => { console.log('bar!'); }) program.parse();
两种方案调整后,执行node test.js --foo bar的输出均为:
foo! bar!
内容的提问来源于stack exchange,提问作者yegor256
相关产品推荐
相关产品推荐

