美文网首页Java 核心技术
解决 node commander 子命令执行异常的问题

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

作者: HoPGoldy | 来源:发表于2019-06-20 09:55 被阅读0次

    问题

    最近在使用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()是基于整个命令行原型进行挂载的。从而导致了 调用某一子命令时会异常触发其他子命令 问题的产生。

    相关文章

      网友评论

        本文标题:解决 node commander 子命令执行异常的问题

        本文链接:https://www.haomeiwen.com/subject/yugrqctx.html