NodeJS 最佳实践

本文是“NodeJS 最佳实践”教程,分上下两个部分。

上篇

人们总是问我们关于Node.js的最佳实战和技巧,所以打算通过这篇文章解释清楚,并总结一下我们在RisingStack公司写代码的经验。

Node.js最佳实战中的一部分是编码规范,另一部分则是处理开发流程。

编码规范

回调惯例

模块应该公开一个错误优先(error-first)的回调接口。

就像下面这样:

确保在回调中检查错误信息

要更好地弄明白为什么必须这样做,先想办法创建一个会挂掉的例子,然后修复它。

首要问题是 readJSON函数,在执行过程中出现了错误,而这个函数却没有做任何错误检查。你务必要先做错误检查。

改进方案:

将回调函数返回

上面的例子还是存在一个错误,就是如果错误发生了,if  中的表达式不会停止运行,而是继续运行下去。这会导致很多未知的错误。长话短说,务必通过回调函数返回。

仅在同步代码中使用try-catch

几乎完美了!但还有一件事,我们必须要小心 JSON.parse。调用JSON.parse 时,如果传入的字符串无法解析成JSON格式,会抛出异常。

由于JSON.parse是同步发生的,我们可以用try-catch包装起来。请注意,你只能对同步代码块做此操作,对回调函数是不起作用的。

尽量避免 this 和 new 关键字

由于Node涉及了大量的回调操作,并且重度使用高阶函数控制流程,因此在Node中绑定一个具体的上下文并不总是行之有效。使用函数式编程风格能避免不少麻烦。

当然,在某些情况下原型(prototype)可能更高效,不过只要可能,还是尽量避免它们。

创建微模块

用unix的方式:

开发者构建一个程序时应该将其分成很多简单的模块,各部分由定义良好的接口整合,所以问题是局部的,并且能通过替换程序部件的方式在将来的版中加入新特性。

不要创建怪兽般的代码,保持简洁,一个模块就只做一件事,但是要做到极致。

使用良好的异步模式

使用async异步处理模块。

错误处理

错误可以分为两部分,操作错误编程错误

操作错误

精心编写的应用程序中也一样会出现操作错误。因为这些不是 bug ,而是由于操作系统或远程服务导致的,例如:

  • 请求超时
  • 系统内存不足
  • 远程连接失败

处理操作错误

根据不同运行错误的类型,你可以采用下面的方式处理:

  • 尝试解决错误——如果文件丢失,你可以提前创建一个。
  • 当处理网络通信时,可以重试操作。
  • 把问题告诉客户,表示有些功能不能正常工作——可以用于处理用户输入。
  • 如果错误无法在当前条件下解决,终止进程,例如应用程序无法读取它的配置文件。

还有,上述的所有处理方式都应该记录日志。

编程错误

编程错误都算是bug。下面所列的几条你应该避免,例如:

  • 调用异步函数时没有回调。
  • 不能读取未定义(undefined)的属性

处理编程错误

如果错误属于bug,立刻终止程序,你并不知道应用当前的运行状态。当错误发生时,进程控制系统应该会重启应用程序,例如:supervisord 或者 monit

工作流技巧

使用 npm init 创建新项目

init 命令可以帮助你创建应用程序的 package.json 配置文件。文件设置了一些默认配置,之后可以修改。

创建一个优秀的项目应该这样开始:

指定开始和测试脚本。

在你的 package.son 文件中,你可以在 scripts 部分中设置脚本。npm init  默认会创建两个,start 和 test 脚本。可以通过 npm start 和 npm test 命令运行。

还有,作为加分项:你可以在这里加入自定义脚本,通过 npm run-script <SCRIPT_NAME> 来运行。

注意,NPM 会通过设置 $PATH 来扫描 node_modules/.bin 下的所有可执行脚本。这样可以避免安装全局的 NPM 模块。

环境变量

生产部署和演示部署都应该由环境变量来实现。最主流的实现方式是同时在生产和演示中设置 NODE_ENV变量。

根据你设置的环境变量,你可以使用 nconf 模块来加载配置信息。

当然,你也可以在你的Node.js 应用中使用其它环境变量设置 process.env,这是一个包含了用户环境的对象。

不要重新发明轮子

务必优先寻找现成的解决方案。NPM 的库超级多,涵盖了你平时需要的大部分功能。

使用风格指南

所有的代码都保持统一风格有助于理解大型代码库。其中应该包含缩进、变量命名、最佳实践以及其他方面。

如果想看一个实际的例子,请查看  RisingStack 编写的 Node.js 风格指南

后记

我希望这篇文章对你编写Node.js有所帮助,并且解决一些令你头疼的难题。下篇文章会继续探讨操作技巧和最佳实践。

你可以从 持续部署Node.js 应用 阅读部署相关的技巧。
还有,我们将于 11月21日举办名为  One-Shot Budapest 的 Node大会(NodeConf)。关注PayPal、NPM、Strongloop分享的经验。希望到时能看到你。

下篇

你应该还记得我们上篇的Node.js 最佳实践。这篇文章里我们继续讨论更多的最佳实践,这些实践有助于你成为更棒的Node.js开发者

保持风格一致

当在一个较大的团队里开发JavaScript 应用程序时,创建一个所有人都遵守的风格指南非常重要。如果你想找灵感,我会推荐你去阅读 RisingStack 的 Node.js 风格指南

但是这只是起步——当你设置好标准,所有团队成员都必须遵守风格指南。这是 JSCS 诞生的原因。

JSCS 是一个JavaScript 编码风格检查工具。将JSCS加入项目对你来说小菜一碟:

你需要做的下一步关键就是在 package.json 文件中加入下面的代码来开启它:

当然,你也可以加入多个文件、目录检查。但为什么我们仅仅在 package.json 文件中创建了一个自定义的脚本呢?我们是以本地的方式安装 jscs 的,所以在一个系统中可以有多个不同版本。这样还能正常工作是因为NPM 执行时会将 node_modules/.bin  设置到 PATH上。

你可以在 .jscsrc 文件中定义验证规则,或者使用预设规则。从这里可以查看可用的预设,通过 --preset=[PRESET_NAME]来应用。

执行 JSHint、JSCS 规则

你的构建过程还应该包含 JSHint 和 JSCS,不过在开发者的电脑上运行 pre-commit checks 或许是个不错的主意。

要实现这个很简单,你可以使用 pre-commit NPM 库:

然后在 package.json 文件中作如下配置:

注意,pre-commit 将会扫描 package.json中script里的所有脚本。开启以后,每次提交时都会自动进行检查。

用JS替换JSON做配置

我们看到大量的项目都是使用JSON文件做配置的。这是目前最普遍的做法,JS配置文件则能够提供更大的灵活度。所以我们推荐你使用 config.js 文件:

使用 NODE_PATH

你是否曾经碰到过下面这种情况?

当你的项目结构变得错综复杂,模块依赖会非常麻烦。要解决这个问题有两个办法:

  • 把你的模块软链接到node_modules目录下。
  • 使用 NODE_PATH。

在RisingStack我们使用 NODE_PATH的方式,因为将所有相关文件软链接到 node_modules目录需要大量额外的工作,并且在很多操作系统下都不适用。

设置 NODE_PATH

假设你的项目结构是这样的:

0EA2EA61-DF4B-466F-9AFB-4EC56C5CA161

我们可以使用 指向 lib 目录的NODE_PATH,而不是使用相对路径。在我们的package.json 的 start script部分,我们使用NODE_PATH设置并且用npm start 运行项目。

依赖注入

依赖注入是一种软件设计模式,是指将一到多个依赖(或服务)注入或通过引用的方式引入到需要依赖的对象。 

依赖注入在测试中非常有用。使用这个模式你可以轻松模拟模块间的依赖关系。

上面的例子中我们有两个不通过的 db。在 index.js 文件中是“真实的” db 模块,而第二段代码中我们只是简单地创建了一个模拟的db模块。

这样我们在测试时就可以轻松地将模拟的依赖引入模块。

开发应用时需要一臂之力?

RisingStack 提供了 JavaScript 开发和咨询服务——如果你需要帮助请联系我们!

1 5 收藏 评论

关于作者:段昕理

因为iPod而喜欢上苹果的一系列产品,非常认同他们追求极致的精神。工作之余,喜欢前端的开源项目,Github(https://github.com/sandywalker) 个人主页 · 我的文章 · 15 ·    

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部