nodejs 工具库zx.js源码解析(一)

1,133 阅读2分钟

最近很火的zx.js,封装了一些nodejs工具库,相比shelljs,zx.js使用起来更方便,受到这么多人的喜欢,zx肯定有一些我们可以学习的优点。那么我们能从zx.js学到哪些知识点,设计模式,方法,从而运用到以后的工作呢?

.mjs

zx.js运用了ES Module的引入方式 .mjs是ES Module模块引入方式的扩展名,我们可以在高版本的nodejs中使用,跟nodejs最初的Common js 模块引入方式他有一些优势。

image.png

  1. Cjs是同步加载,优点是灵活,确定也很明显就是无法解决循环引用的问题,而且Cjs是同步加载的,会导致加载过慢的问题
  2. 而ESM是异步加载,会加快依赖的加载速度,而且静态加载的特点也解决了循环引用的问题和循环引用依赖的问题。 如果大家想在ESM文件行内代码中引入模块,我们应该怎么做呢?在zx中作者为我们提供了方案使用nodejs module模块的createRequire

image.png

process.argv获取输入参数

平时在用shelljs开发node工具的时候只知道在对应的command传入info,从而进行处理 但是当我们需要对所有输入的命令进行校验,二次处理,那么这个数据在哪呢?答案就是process.argv。

image.png

util中的promisify

promisify可以把普通函数包装成promise函数

image.png

正则表达式拆分写

zx的quote方法的正则,是多个正则组合起来的。有时候我们在写一个逻辑很长的正则时,感觉头大,不妨可以拆开写,一来更容易维护,二来更容易看懂。

image.png

使用多个if else 考虑能不能用策略模式重构

zx.js中的transformMarkdown函数感觉写了太多if else,这时候我们本着取其精华去其糟粕的原则,其中的root部分代码可以重构成这样

image.png

async function loop(arr) {
  for(const [con, data] of arr) {
    if(con) {
      return data
    }
  }
}

async function transformMarkdown(source) {
  let output = []
  let state = 'root'
  let prevLineIsEmpty = true
  for (let line of source.split('\n')) {
    const loopArr = [
      [state === 'root' && /^( {4}|\t)/.test(line) && prevLineIsEmpty, {output: line, state: 'tab'}],
      [state === 'root' && /^```(js|javascript)$/.test(line), {output: line, state: 'tab'}],
      [state === 'root' && /^```(sh|bash)$/.test(line), {output: line, state: 'tab'}],
      [state === 'root' && /^```.*$/.test(line), {output: line, state: 'tab'}],
      [state === 'root' && true, {output: line, state: 'tab'}]
    ]  
    const { output: outVal, state: stateVal } = await loop(loopArr)
    output.push(outVal)
    state = stateVal
  }
  return output.join('\n')
}

这样做虽然加了一层循环,但是在后期维护的时候我们只需要修改loopArr中的[conditon, data]形式的代码,便于维护看起来也整洁,其他的判断数据也类似的加到loopArr中。个人想法,不喜勿喷。