阅读更多

1顶
0踩

编程语言

转载新闻 Node.js 最佳编程实践

2015-07-29 14:40 by 副主编 mengyidan1988 评论(2) 有5903人浏览
本文谈一谈Node.js的最佳实践,包括Node.js的代码风格以及开发者工作流。

代码风格

回调约定
模块应该暴露错误优先的回调接口。
module.exports = function (dragonName, callback) {  
  // do some stuff here
  var dragon = createDragon(dragonName);

  // note, that the first parameter is the error
  // which is null here
  // but if an error occurs, then a new Error
  // should be passed here
  return callback(null, dragon);
}

总是在回调中检查错误: 为了理解这一点,我们从一个违反该规则的例子看起
// this example is **BROKEN**, we will fix it soon :)
var fs = require('fs');

function readJSON(filePath, callback) {  
  fs.readFile(filePath, function(err, data) {  
    callback(JSON.parse(data));
  });
}

readJSON('./package.json', function (err, pkg) { ... }

readJSON函数的最主要的问题是,如果在执行过程中发生Error,它并不会检查这个错误。
改进版本如下:
// this example is **STILL BROKEN**, we are fixing it!
function readJSON(filePath, callback) {  
  fs.readFile(filePath, function(err, data) {
    // here we check, if an error happened
    if (err) {
      // yep, pass the error to the callback
      // remember: error-first callbacks
      callback(err);
    }

    // no error, pass a null and the JSON
    callback(null, JSON.parse(data));
  });
} **在回调中返回!**

上面代码仍然存在的问题是,当Error发生的时候,程序的执行并不会在if语句中停止,而是会继续。这回导致很多意料之外的问题。正如上面加粗部分提到的,总是在回调中返回!
// this example is **STILL BROKEN**, we are fixing it!
function readJSON(filePath, callback) {  
  fs.readFile(filePath, function(err, data) {
    if (err) {
      return callback(err);
    }

    return callback(null, JSON.parse(data));
  });
} **只在同步代码中使用try-catch**

有一点需要注意的是,JSON.parse在无法将指定的字符串格式化为JSON格式的时候会抛出一个异常。

因为JSON.parse是一个同步函数,因此我们可以将其包围在try-catch语句块中。一定要注意的是,只有同步代码块才能使用try-catch,你不能用在回调中!
// this example **WORKS**! :)
function readJSON(filePath, callback) {  
  fs.readFile(filePath, function(err, data) {
    var parsedJson;

    // Handle error
    if (err) {
       return callback(err);
    }

    // Parse JSON
    try {
      parsedJson = JSON.parse(data);
    } catch (exception) {
      return callback(exception);
    }

    // Everything is ok
    return callback(null, parsedJson);
  });
}

避免this和new

在Node中与指定的上下文绑定并不是总是个好事,因为在Node程序中经常涉及到传递回调函数,并且会经常使用高层函数管理工作流。函数风格的编程方式会帮你避免很多麻烦。

创建小模块

使用Unix的方式:
引用

Developers should build a program out of simple parts connected by well defined interfaces, so problems are local, and parts of the program can be replaced in future versions to support new features.

保持模块足够小(内聚),模块应该只做一件事!

使用好的同步模式

使用async

错误处理

错误主要分为两种:操作错误(operational errors)和程序员错误。
Operational errors

例如:
  • 请求超时
  • 系统内存不足
  • 连接远程服务失败

处理Operational errors

Log everything! 启用日志服务!
程序员错误

程序员错误即是程序的bug。这是你可以尽量避免的,比如:
  • 调用异步方法时没有使用回调
  • 无法读取undefined的属性

工作流建议
使用npm init启动一个新项目

init命令帮你创建一个应用的package.json文件,并且会设置一些初始值,便于你后期进行修改。试着用这个命令启动一个新项目吧:
mkdir my-awesome-new-project  
cd my-awesome-new-project  
npm init


指定一个start和test脚本

在package.json中你可以使用script属性设置脚本。默认情况下,npm init会生成两个,start和test。你可以使用npm start和npm test执行他们。

当然你也可以定义自己的脚本,使用如下命令执行npm run-script <SCRIPT_NAME>。

注意,NPM会设置$PATH来查找node_modules/.bin中的可执行文件。这可以避免安装全局的NPM模块。也就是说,例如grunt这样的工具,你可以只安装在项目中,而不是全局安装这个NPM模块。

环境变量

在生产和开发环境可能需要设置不同的环境变量,最通常的方法是通过NODE_ENV来分别设置production或staging。

基于不同的环境变量,你可以载入不同的配置信息,例如可以借助nconf模块

当然你也可以利用process.env在你的Node.js应用程序中使用其他的环境变量,也就是你可以在一个对象中包含用户环境。

可以参考Node的对应文档
不要重复发明轮子

首先寻找已有的解决方案。NPM中包括非常丰富的包,所以请最大化的利用这些资源。

使用风格指南

可以参考RisingStack的Node.js风格指南

References
本文翻译自:https://blog.risingstack.com/node-js-best-practices/
译文来自:http://wwsun.me/
1
0
评论 共 2 条 请登录后发表评论
2 楼 windlike 2015-08-05 10:13
题目写的有点大
1 楼 mangguo 2015-07-30 11:12
代码风格这方面的东西很是受益匪浅,thanks最近也是在学nodejs

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • Windows 动态库编程技术 C++ 库文件三种模式: lib、dll、dll+lib详解及其创建使用

    动态链接库为模块化应用程序提供了一种方式,使得更新和重用程序更加方便,当几个应用程序在同一时间使用相同的函数时,它也帮助减少内存消耗,这是因为虽然每个应用程序有独立的数据拷贝,但是它们的代码是共享的。 C++ 库会涉及到三个东西:.h .lib .dll文件。 库的使用方式有三种: 1&gt;. .h + .lib 2&gt;. .dll 3&gt;. .h + .li...

  • 关于.c .obj .cpp .exe区别

    1. 编辑源代码 代码在.c 和 .h头文件中写好了以后, 从.c 和.h文件编译成.obj文件 命令: cl /c xxx.c --&gt; xxx.obj 2. 编译源文件 代码被编译为二进制文件.obj以后, 打包一些调用的库, 链接成.exe可执行文件 命令: cl xxx.c --&gt; xxx.objandxxx.exe 3. 链接生成应用程序 ...

  • C++ : XML 文件解析(依赖库:TinyXml)

    XML 文件解析步骤与 Demo,推荐三方库 TinyXML

  • c++程序编译后自动生成的文件有什么用

    1, PCH文件 预编译头文件(一般扩展名为.PCH),是把一个工程中较稳定的代码预先编译好放在一个文件(.PCH)里.这些预先编译好的代码可以是任何的C/C++代码--甚至可以是inline函数,只它们在整个工程中是较为稳定的,即在工程开发过程中不会经常被修改的代码. 为什么需要预编译头文件?一言以蔽之:提高编译速度.一般地,编译器以文件为单位编译,如果修改了一工程中的一个文件则所有文件都要

  • 【C++】Vscode 中不使用CMakeLists构建C++项目:项目结构、各个文件夹作用、从编码到debug一体化

    首先要明白,vscode只是一个记事本,本身是不能够进行任何程序语言开发的。只不过这个记事本可以安装插件,可以和命令行程序结合起来使用,使得它可以进行开发。 一、Vscode下C++项目的目录结构 首先,类似于我们在IDEA中新建一个普通java项目,项目的目录结构是这样的: 新建一个maven模板的java项目,项目的目录结构是这样的: 构建一个web模板的java项目,项目的目录结构是这样的: 用springboot模板构建一个java项目,项目的目录结构是这样的: 对于C++.

  • C语言中的文件是什么?

    C语言中的文件是什么? 1,文件的主要作用是保存数据 2,操作系统中、不同的硬件设备也看做一个文件,对硬件设备文件的操作、等同于对磁盘上普通文件的操作。 如: 把键盘作为标准输入文件、把显示屏输出内容作为标准输出文件 3,常见的硬件设备所对应的文件: 文件 硬件设备 stdin 标准输入文件 如键盘 stdout 标准输出文件 如显示器 stde...

  • visual C++ 项目和解决方案的区别

    项目:         项目是构成某个程序的全部组件的容器,该程序可能是控制台程序、基于窗口的程序或某种别的程序。程序通常由一个或多个包含用户代码的源文件,可能还要加上包含其它辅助数据的文件组成。某个项目的所有文件都存储在相应的项目文件夹中,关于该项目的详细信息存储在一个扩展名为.vcproj的xml文件中,该文件同样存储在相应的项目文件夹中。项目文件夹还包括其它文件夹,它们用来存储编译及链接项

  • 彻底搞懂一个项目中的各种文件关系

    一个项目由很多文件构成,很多.c文件,和.h文件。 .h文件,只是头文件中的包含的作用,就是copy。 编译的时候,各个.c文件分别进行编译。 如果一个.c文件中的变量,使用之前是用extern修饰的,那么表明这个变量不是本文件中的,是别的文件中的。extern 表示外部的意思,就是表明这个变量或者函数,不是本文件中的,是其他.c文件中的。各个.c文件都编译后,需要进行链接的。 重要的补充说明: 头文件中不可以有可执行的代码! 什么叫可执行代码,自己去Google。 否则,如果头文件中有可执行代码,那么如

  • 对于编译原理的理解

    编译原理 今天组长教育了一下整个程序的编译过程,感觉自己对于这块了解还是很少,有许多知识之前知道,现在忘记了,还有很多规则只是知道,但并不知道它为什么要这样写,所以再次记录一下,有什么问题或者错误希望大家在评论区提出。。。。 编译原理 如图 预编译阶段 在预编译阶段,发挥作用的是预处理器(CPP)。预处理器读取.cpp文件,对其中的伪指令(#开头的指令)和特殊符号进行处理,...

  • c++编译 (.obj, .lib, .dll, .exe的关系(附:lib和DLL的区别))

    转载原网址 c++程序在编译后,在目标路径下会生成多个文件: Debug文件夹(*.exe,*.ilk,*.obj,*.pch,*.pdb,*.idb,*,pdb),*.cpp,*.dsp,*.ncb,*.plg *.exe:是生成的可执行文件 *.ilk:当选定渐增型编译连接时,连接器自动生成ILK文件,记录连接信息 *.obj:是目标文件,源程序编译后的产物 *.pch:全称是PreCompiled Header,就是预先编译好的头文件 *.idb:文件保存的信息,使编译器在重新编译的时候只重编译最新

  • .obj, .lib, .dll, .exe的关系(附:lib和DLL的区别)

    lib是和dll对应的。     lib是静态的库文件,dll是动态的库文件。     所谓静态就是link的时候把里面需要的东西抽取出来安排到你的exe文件中,以后运行     你的exe的时候不再需要lib。     所谓动态就是exe运行的时候依赖于dll里面提供的功能,没有这个dll,你的exe无法运     行。         lib,   dll,   exe都算是最终的目标文件,是

  • 编译.cpp文件为.obj文件成功后,要将所有的obj文件连接成为.exe文件

    编译.cpp文件为.obj文件成功后,要将所有的obj文件连接成为.exe文件。这时出错原因通常有3个:1 。某个函数,在不同的cpp文件中有重复的定义,即有2个函数体的实现; 2.调用某个函数时,无法确定调用哪个,即函数参数类型或个数无法匹配; 3.动态性声明错误如果在类定义(.H文件)中声明了使用动态性,则在类实现部分(.cpp文件)要加相应的说明,如正方形类的序列化声明://Square...

  • C/C++之cpp变exe

    C/C++之cpp变exe 上节我们讲了C/C++的命名空间。 本节我们来介绍如何把源代码转换成软件。也就是标题所说的cpp变exe。 大家在使用vs等IDE的时候是不是发现很方便,只要写完源码,源码没错误的情况下,点一下生成就会得到可执行文件(exe)。 但是大家有没有想过其中的原理是怎么样的呢。所以本节通过这一点来展开做介绍。 点击生成解决方案就可以快速获得可执行文件,细心的同学可能会发现项目的Debug或者Release文件夹中,会有需多奇怪后缀的文件。例如我拿上节的方案Debug目录中的文

  • c++编译成的 .obj文件 与exe文件的区别

    今天看以篇技术博客的时候,看到.obj文件,对.obj文件有点印象,但不是很清楚。于是查了些资料和博客,得到一些个人总结。以此与大家分享。 概述:         目标文件,一般是程序编译后的【二进制文件】,再通过链接器和资源文件链接就成可执行文件了。 OBJ只给出了程序的【相对地址】,而可执行文件是【绝对地址】。 关系: 理解1: 编译:当前源代码编译成二进制目标文件(.obj文

  • 创建一个Android程序(简单介绍工程里面各个文件的作用)

    1.创建的时候:Min SDK Version是指可以兼容的最小的SDK版本。 2.工程右边的各个文件: 1) src ---放置的是源文件,即java代码 2) gen---里面的东西不要动,R.java是Eclipse自动生成的,里面包含了一些类,全部是public staticfinal class,其中类里面也都是public static finalint类型的变量,变

  • C++文件依存关系

    如果现在你做的C++项目(课题)包含的文件没有超过1000个,你可以选择略过此文,不过建议继续浏览。 如果你觉得重新编译文件的时间很短或者时间长一点无所谓,反正需要重新编译,那么你也可以选择略过此文,不过也建议浏览。 如果你想学习或者关心这块内容,那么此文必定会给你带来收获。 首先我不给出依存关系的定义,我给出一个例子。 1 class Peopel{ 2 public...

  • C/C++项目中.h和.inc文件区别

    原问题:Difference between .h files and .inc files in c C/C++的标准惯例是将class、function的声明信息写在.h文件中。.c文件写class实现、function实现、变量定义等等。然而对于template来说,它既不是class也不是function,而是可以生成一组class或function的东西。编译器(compiler)为了...

  • 结合编译过程,分析C++头文件和源文件的区别

    头文件和源文件的区别 头文件和源文件在本质上没有任何区别。 只不过一般:后缀为 .h 的文件是头文件,内含函数声明、宏定义、结构体定义等内容。后缀为 .c 的文件是源文件,内含函数实现,变量定义等内容。而且是什么后缀也没有关系,只不过编译器会默认对某些后缀的文件采取某些动作。这样分开写成两个文件是一个良好的编程风格。 原文链接:https://blog.csdn.net/qq_30815237/article/details/88948632 ...

Global site tag (gtag.js) - Google Analytics