We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
commander.js 7.0.0版本的核心代码就一个文件index.js,2200多行代码,代码的注释比较丰富,代码可读性也是不错的,感兴趣的同学可以通读一下。
index.js
commander.js包含以下类:
Option
Help
Command
CommandError
InvalidOptionArgumentError
如下图:
Options类的实例存储选项的各类信息:
--no-xx
-c, --cheese
命令行实例执行program.option("-c, --cheese", "add cheese"),会创建一个新的Option实例,存储该选项的各类信息。
program.option("-c, --cheese", "add cheese")
Option类内部通过各种正则和字符串的计算各类信息。
比如,Option类接受参数的长短名称有三种写法:
"-c, --cheese"
"-c|--cheese"
"-c --cheese"
其解析参数的时候以正则/[ |,]+/对字符串做分隔计算: flags.split(/[ |,]+/)。
/[ |,]+/
flags.split(/[ |,]+/)
Help类主要负责帮助信息的展示、配置等工作。
比如执行命令行node index.js -h会打印出:
node index.js -h
Usage: index [options] Options: -v, --version output the version number -d, --debug output extra debugging -c, --cheese <type> cheese type (default: "blue") -b, --banana [type] banana type -i, --integer <number> integer argument -h, --help display help for command
Help类中相对值得说的是formatHelp方法了。
formatHelp
formatHelp接收当前命令行和help实例对象,返回格式化后的帮助信息。
在生成帮助信息的过程中,有几个小的编程技巧可以借鉴:
日志信息字符串,通过数组形式组织,最终拼接为字符串
该方法对比直接拼接字符串,代码可维护性更强。
利用String.prototype.padEnd方法实现字符串补全
String.prototype.padEnd
日常工作中用到该方法的场景可能不多,容易遗漏。
比如:'hello'.padEnd(7, '~')的结果是hello~~。
'hello'.padEnd(7, '~')
hello~~
在formatHelp里用空格补全,用于字符串显示的格式化。
Command类是commander.js的核心类,提供了命令行的各类方法。
下图是Command类使用时的主要流程:
我们简要介绍下其中的一些点:
version(str, flags, description)
该方法注册了命令的版本信息,利用createOption()实现的一个快捷方法。
createOption()
command(nameAndArgs, actionOptsOrExecDesc, execOpts)
该方法注册子命令,有两种模式:
绑定函数实现命令
program .command('start') .action(function() { console.log('actor'); });
执行node index start的时候,会执行action注册的回调,打印actor。
node index start
action
actor
启动独立文件执行命令
program.command('start', 'start runner');
执行node index start的时候,会启动index-start.js文件。
index-start.js
该方法内部通过是否含有描述信息判断是哪种模式。
重复注册命令时,会使用第一个注册的命令
比如:
program .command('start') .action(function() { console.log('start 1'); }); program .command('start') .action(function() { console.log('start 2'); });
在执行node index start的时候,只会打印start 1,因为内部找到匹配的命令的代码是:
start 1
this.commands.find(cmd => cmd._name === name || cmd._aliases.includes(name));
Array.prototype.find方法会返回数组第一个匹配的元素。
Array.prototype.find
EventEmitter在Command类中的使用
Node内置模块EventEmitter提供了事件机制,最常见的api是on/emit。
EventEmitter
on/emit
Command类中几处利用事件机制的地方举例:
option:${optionName}
on(option:${optionName})
emit(option:${optionName})
this.listenerCount('command:*')
command:xx
*
下图是Commander.js内部定义的几个Error类的继承关系。
在内部实现上,分别定义了每个类自身的特殊字段。但值得注意的是,Error.captureStackTrace(this, this.constructor)被频繁使用。
Error.captureStackTrace(this, this.constructor)
Error.captureStackTrace使用
Error.captureStackTrace
Error.captureStackTrace(targetObject[, constructorOpt])
其作用是在targetObject中添加一个stack属性。当访问targetObject.stack时,将以字符串的形式返回Error.captureStackTrace方法被调用时的代码位置信息。举例:
targetObject
stack
targetObject.stack
> 1 const myObject = {}; > 2 Error.captureStackTrace(myObject); > 3 console.log(myObject.stack);
执行node index.js后,终端输出:
node index.js
Error at Object.<anonymous> (xxx/index.js:2:7) at Module._compile (internal/modules/cjs/loader.js:689:30) at ... at ...
当传入constructorOpt时,代码如:
constructorOpt
> 1 function MyError() { > 2 Error.captureStackTrace(this, MyError); > 3 } > 4 > 5 console.log(new MyError().stack)
终端输出:
Error at Object.<anonymous> (xxx/index.js:5:13) at Module._compile (internal/modules/cjs/loader.js:689:30) at ... at ...
可以看出,MyError函数内部的堆栈细节被隐藏了。
MyError
Error.captureStackTrace优点
相对于new Error().stack,Error.captureStackTrace有以下优点:
new Error().stack
更简洁
无需new一个新的Error对象,节省内存空间,同时代码上也会更加优雅。
一般而言,捕获错误信息通常的做法是:
try { new Error(); } catch(err) { // err.stack 包含了堆栈信息,可以对其处理 }
而使用Error.captureStackTrace可以直接获取堆栈信息,实现方式更简洁。
更安全
如果需要忽略部分堆栈信息,使用Error.captureStackTrace会更加方便,无需手工操作。
更少资源
使用Error.captureStackTrace时,只有访问targetObject.stack时,才会进行堆栈信息的格式化工作。
如果targetObj.stack未被访问,则堆栈信息的格式化工作会被省略,从而节省计算资源。
targetObj.stack
Error.captureStackTrace使用场景
Error.captureStackTrace并不是Node.js创造的,而是V8引擎的Stack Trace API。语法上,Node.js中的Error.captureStackTrace()与V8引擎中所暴露的接口完全一致。
Error.captureStackTrace()
事实上,Node.js的Error类中,所有与stack trace有关的内容均依赖于V8的Stack Trace API。
因此,Error.captureStackTrace(targetObject[, constructorOpt])使用的场景有:
基于V8引擎的运行环境,如Node.js、Chrome浏览器
Error.captureStackTrace(this, MyError)
作用也是隐藏构造函数内部的堆栈信息,但需要明确指定构造函数名,通用性不强。
Error.captureStackTrace(this, arguments.callee)
arguments.callee表示当前函数,也有通用性。但ES3及之后的严格模式禁用了arguments.callee,因此不建议使用。
arguments.callee
该做法可以隐藏构造函数内部的堆栈信息,无需指定构造函数名,通用型强。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
概览
commander.js 7.0.0版本的核心代码就一个文件
index.js
,2200多行代码,代码的注释比较丰富,代码可读性也是不错的,感兴趣的同学可以通读一下。commander.js包含以下类:
Option
Help
Command
CommandError
InvalidOptionArgumentError
如下图:
Option类
Options类的实例存储选项的各类信息:
--no-xx
类型的选项-c, --cheese
命令行实例执行
program.option("-c, --cheese", "add cheese")
,会创建一个新的Option
实例,存储该选项的各类信息。Option类内部通过各种正则和字符串的计算各类信息。
比如,Option类接受参数的长短名称有三种写法:
"-c, --cheese"
"-c|--cheese"
"-c --cheese"
其解析参数的时候以正则
/[ |,]+/
对字符串做分隔计算:flags.split(/[ |,]+/)
。Help类
Help类主要负责帮助信息的展示、配置等工作。
比如执行命令行
node index.js -h
会打印出:Help类中相对值得说的是
formatHelp
方法了。formatHelp
接收当前命令行和help实例对象,返回格式化后的帮助信息。在生成帮助信息的过程中,有几个小的编程技巧可以借鉴:
日志信息字符串,通过数组形式组织,最终拼接为字符串
该方法对比直接拼接字符串,代码可维护性更强。
利用
String.prototype.padEnd
方法实现字符串补全日常工作中用到该方法的场景可能不多,容易遗漏。
比如:
'hello'.padEnd(7, '~')
的结果是hello~~
。在
formatHelp
里用空格补全,用于字符串显示的格式化。Command类
Command类是commander.js的核心类,提供了命令行的各类方法。
下图是Command类使用时的主要流程:
我们简要介绍下其中的一些点:
version(str, flags, description)
该方法注册了命令的版本信息,利用
createOption()
实现的一个快捷方法。command(nameAndArgs, actionOptsOrExecDesc, execOpts)
该方法注册子命令,有两种模式:
绑定函数实现命令
执行
node index start
的时候,会执行action
注册的回调,打印actor
。启动独立文件执行命令
执行
node index start
的时候,会启动index-start.js
文件。该方法内部通过是否含有描述信息判断是哪种模式。
重复注册命令时,会使用第一个注册的命令
比如:
在执行
node index start
的时候,只会打印start 1
,因为内部找到匹配的命令的代码是:Array.prototype.find
方法会返回数组第一个匹配的元素。EventEmitter在Command类中的使用
Node内置模块
EventEmitter
提供了事件机制,最常见的api是on/emit
。Command类中几处利用事件机制的地方举例:
option:${optionName}
事件(on(option:${optionName})
),在命令行执行时触发回调(emit(option:${optionName})
)。this.listenerCount('command:*')
获取command:xx
事件(*
为通配符)的监听者数量,决定是否触发该事件Error类
下图是Commander.js内部定义的几个Error类的继承关系。
在内部实现上,分别定义了每个类自身的特殊字段。但值得注意的是,
Error.captureStackTrace(this, this.constructor)
被频繁使用。Error.captureStackTrace
使用Error.captureStackTrace(targetObject[, constructorOpt])
其作用是在
targetObject
中添加一个stack
属性。当访问targetObject.stack
时,将以字符串的形式返回Error.captureStackTrace
方法被调用时的代码位置信息。举例:index.js
执行
node index.js
后,终端输出:当传入
constructorOpt
时,代码如:终端输出:
可以看出,
MyError
函数内部的堆栈细节被隐藏了。Error.captureStackTrace
优点相对于
new Error().stack
,Error.captureStackTrace
有以下优点:更简洁
无需new一个新的Error对象,节省内存空间,同时代码上也会更加优雅。
一般而言,捕获错误信息通常的做法是:
而使用
Error.captureStackTrace
可以直接获取堆栈信息,实现方式更简洁。更安全
如果需要忽略部分堆栈信息,使用Error.captureStackTrace会更加方便,无需手工操作。
更少资源
使用
Error.captureStackTrace
时,只有访问targetObject.stack
时,才会进行堆栈信息的格式化工作。如果
targetObj.stack
未被访问,则堆栈信息的格式化工作会被省略,从而节省计算资源。Error.captureStackTrace
使用场景Error.captureStackTrace
并不是Node.js创造的,而是V8引擎的Stack Trace API。语法上,Node.js中的Error.captureStackTrace()
与V8引擎中所暴露的接口完全一致。事实上,Node.js的Error类中,所有与stack trace有关的内容均依赖于V8的Stack Trace API。
因此,
Error.captureStackTrace(targetObject[, constructorOpt])
使用的场景有:基于V8引擎的运行环境,如Node.js、Chrome浏览器
Error.captureStackTrace(this, MyError)
作用也是隐藏构造函数内部的堆栈信息,但需要明确指定构造函数名,通用性不强。
Error.captureStackTrace(this, arguments.callee)
arguments.callee
表示当前函数,也有通用性。但ES3及之后的严格模式禁用了arguments.callee
,因此不建议使用。Error.captureStackTrace(this, this.constructor)
该做法可以隐藏构造函数内部的堆栈信息,无需指定构造函数名,通用型强。
The text was updated successfully, but these errors were encountered: