0
点赞
收藏
分享

微信扫一扫

解决 node commander 子命令执行异常的问题

问题

最近在使用commander制作命令行工具时遇到了这样一个问题:在调用单个子命令的时候,该命令行工具下的所有子命令都被触发了!如下,我在app.js里定义了两个子命令configadd,然后调用config子命令时,可以看到add子命令也被触发了。

app.js 文件

const program = require('commander')

// config 子命令
program
    .command('config', '设置本程序')
    .action(() => {
        console.log('config 执行!')
    })

// add 子命令
program
    .command('add', '添加设置')
    .action(() => {
        console.log('add 执行!')
    })

program.parse(process.argv)

调用

> node app.js config

config 执行!
add 执行!

解决

出现这个问题个根本原因在于 子命令介绍的设置问题,应使用description()方法来设置介绍内容,而不是command()的第二个参数。将问题代码改成如下形式即可解决问题(所有的子命令都要改成这样):

// 错误写法
program
    .command('config', '设置本程序')
    .action(() => {
        console.log('config 执行!')
    })
// 正确写法
program
    .command('config')
    .description('设置本程序')
    .action(() => {
        console.log('config 执行!')
    })

原因

出现这个问题的原因是因为command方法在接受不同数量的参数时会返回不同的对象导致的,如果它只接受一个参数子命令名的话返回的是 子命令本身,而如果加上第二个参数子命令介绍的话,返回值就变成了整个命令行的原型!

command() 不添加第二个参数

console.log(program.command('config'))

// 返回子命令对象
{
  ...
  _name: 'config',
  _noHelp: false,
  parent: // 这里可以看到父节点,证明返回值是子命令本身
    Command {
      ...
    }
}

command() 添加第二个参数

console.log(program.command('add', '添加设置'))

// 返回整个命令行原型
{
  commands: [ // 所有的子命令
     Command { ... }, // 子命令1
     Command { ... }  // 子命令2
  ],
  options: [ ... ], // 命令行工具全局的参数
  ...
}

这么设计的原因是command(key, describe)这种写法是为了方便使用 子命令模式 的链式调用的,所以才会返回整个原型,如下,如果不使用子命令模式的话就不要用这种方式来设置子命令的介绍:

const program = require('commander')

program
    .version('1.0.0')
    .description('这是一个命令行工具')
    .command('add', '第一个命令')
    .command('config', '第二个命令')
    .command('list', '第三个命令')
    .parse(process.argv)

这样一来就清楚了,如果使用了给command()添加第二个参数的形式来创建子命令的话,它就会返回整个命令行的原型,再加上后面还链式调用了action方法,这就导致了action()是基于整个命令行原型进行挂载的。从而导致了 调用某一子命令时会异常触发其他子命令 问题的产生。

举报

相关推荐

0 条评论