Node.js / JavaScript后端开发指引

简介: 这是一篇关于后端 JavaScript 开发的指引,如果你对 JavaScript 的认识仍然停留在前端开发的话,你需要更新自己的知识体系了。 用 NPM 来做项目管理和包维护 用 Grunt 来做代码格式修整、Lint 和其他自动化任务 用 CoffeeScript 方言写更友好的 Ja...

这是一篇关于后端 JavaScript 开发的指引,如果你对 JavaScript 的认识仍然停留在前端开发的话,你需要更新自己的知识体系了。



Web 开发框架从以前流行的 LAMP/LEMP  架构逐渐转移到 Ruby on Rails 和 Python Django 架构之上。但最近有另外几种的架构变得成熟了:比如 Golang, Clojure/leiningen,  Node.js 。这三者之中我更关注 Node.js。原因是它的生态更加完善。所以最近的几个项目都是用它来实现的。Node.js 既适合做后端 API 的粘合,也适合给终端用户提供 API 。

 

用 NPM 来做项目管理和包维护

Node.js 的每个项目都应该有一个 package.json 配置文件。其中包含了这个项目或者库的信息和所依赖的库。一个相对完成的 package.json 文件像这样:

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "description": "My app and service",
  "main": "app.js",
  "scripts": {
    "start": "forever start app.js",
    "test": "mocha test"
  },
  "dependencies": {
    "coffee-script": "=1.4.0",
    "express": "=3.0.6",
    "mocha": "=1.7.4",
    "underscore": "=1.4.3",
    "forever": "=0.10.0",
    "async": "",
    "grunt-beautify": ""
  },
  "repository": "",
  "author": "Bruce Dou",
  "license": "BSD"
}

这个文件可以在你的项目目录下执行 npm init 来按指引创建。注意其中的 scripts 部分,这里可以创建很多自定义命令。比如如此配置之后,npm start 会执行 forever start app.js 命令。

用 Grunt 来做代码格式修整、Lint 和其他自动化任务

Grunt 是一个命令行任务自动化工具。它包含了很多有用的插件。可以实现代码美化、自动化部署、自动生成 sprit、自动创建项目模板、自动压缩前端代码、自动编译 coffescript 等等你能想到的任务。假如你找不到自己需要的功能,还可以自己开发 Grunt 插件来实现。它的配置文件是位于项目根目录的 grunt.js 。一般项目都需要的功能是代码美化和 Lint,配置文件象这样:

module.exports = function (grunt) {
  // Project configuration.
  grunt.initConfig({
    beautify: {
      files: ['grunt.js', '*.js', 'lib/*.js']
    },
    lint: {
      files: ['grunt.js', '*.js', 'lib/*.js']
    },
    beautifier: {
      options: {
        indentSize: 2
      },
      tests: {
        options: {
          indentSize: 4
        }
      }
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        browser: true
      },
      globals: {
        jQuery: true,
        Drupal: true,
        Backbone: true,
        _: true,
        app: true
      }
    }
  });
  grunt.loadNpmTasks('grunt-beautify');
  //grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.registerTask('default', 'beautify');
};

添加了配置文件之后可以在项目目录运行 grunt 命令自动执行任务串。grunt beautify 可以执行子任务。

用 CoffeeScript 方言写更友好的 JavaScript

CoffeeScript 提供了类似于 Ruby 的语法,简化了 JavaScript 的书写,简化了 JavaScript 中实现类和类的继承的实现。你不必再自己繁琐得通过 prototype 和 constructor,call,apply 实现类的继承。 无论用 VIM 还是 Sublime Text 都可以找到对应的实时转换工具,在写 CoffeeScript 的同时就能看到对应的 JavaScript。

必不可少的几个库

underscore

underscore 是写 JavaScript 必不可少的库。提供了一些非常常用的方法,这些方法不仅使用方便,而且提高了代码的可读性。:

用 _.each 代替 for 循环,比如:

var contents = [];
for(var i in msgs) {
  contents.push(msgs[i].content);
}

可以改写为:

var contents = [];
_.each(msgs, function(el) {
  contents.push(el.content);
});

其他常用的方法还有:

_.map 用来对数组元素进行批量转换

_.reduce 用来将数组元素合并为结果

_.pluck 用来取对象数组中的子元素,返回包含对应子元素的新数组

_.filter 用来有选择性的取数组中的某些值,返回包含符合条件的值的新数组

_.mixin 用来增加自定义函数

_.chain 用来实现函数式编程:

_.chain([1,2,3])
 .map(function(v) {return v * 2;})
 .reduce(function(total, v) { total += v}, 0)
 .value();

Async

Async.js 对常用的流程控制模式进行了封装,比如并行处理、Pipeline等等:

async.parallel 并行处理,整体等待最慢的函数返回,常用作多个后端请求的聚合或者并行处理:

...
// construct call functions
var callItems = [];
function make_query_func(json) {
  return function (callback) {
    callBackService(json, callback);
  };
}
_.each(messages, function (el, i) {
  callItems.push(make_query_func({
    vmsg: messages[i].vmsg,
    cmsg: messages[i].cmsg
   }));
});
// execute the call functions parallelly
async.parallel(callItems, function (err, results) {
  main_cb(results);
});

async.waterfall 可以用来将大量嵌套的函数顺序执行,前一个函数的结果作为下一个函数的参数。用它之后你的代码里将不会再出现过深的 callback 嵌套:

// old way
...
var result = function(uid, callback) {
  get_user_ids(uid, function(err, user_ids) {
    get_content(user_ids, function(err, content) {
      content_clean(content, function(err, clean_content) {
        callback(err, clean_content);
      });
    });
  });
}
// new way
...
async.waterfall([get_user_ids, get_content, content_clean]);

开发 C++ addons 增强和扩展 Node.js

这意味着你不必担心某些逻辑的性能,也不必担心和其他框架的继承。因为所有语言或者开发栈都会提供 C/C++ 的接口。

Node.js 配置管理方式

有两种配置方式,config.js 或者 config.json 假如以 config.js 作为配置文件:

// config.js
exports.config = {'a':'a val', 'b': 'b val'};
// app.js
var config = require('./config').config;

如果以 config.json 作为配置文件:

// config.json
{'a': 'a val', 'b': 'b val'}
// app.js
var config = JSON.parse(fs.readFileSync(process.cwd() + '/config.json'));

开发内部 Service 推荐的部件

  • 进程统计信息,比如 uptime, memory usage, heap size, connection number, 处理的请求数量等等。这样便于和监控系统对接
  • RESTful apis,推荐以 RESTful JSON 格式作为内部通信协议,这其实对大部分应用完全足够,而且容易调试。
  • 配置文件。将可能会发生变化的变量放到配置文件里。
  • Service Level Agreement。比如超过 100ms 的请求报错而不是继续等待返回信息。

Forever: Daemon 管理工具

既然 Node.js 是长时间运行的后台进程,缺不了进程管理工具。Forever 就是为了实现对 Node.js 的 daemon 进程进行管理的工具。常用命令:

forever start app.js 启动进程
forever restart app.js 重启进程
forever list 列出后台进程,并且列出 log 文件,可以方便的及时查看 log 文件内容。

Node.js Cluster

Node.js Cluster 是为了利用多核 CPU 的计算能力, 并且子进程可以共用同一个端口:

var cluster = require('cluster');
if (cluster.isMaster) {
    //start up workers for each cpu
    require('os').cpus().forEach(function() {
        cluster.fork();
    });

} else {
    //load up your application as a worker
    require('./app.js');
}

JavaScript 开发常见问题:

JavaScript 是传值还是传引用?

简单说:如果参数为一个对象则为传引用,如果参数为变量或者函数则为传值。

如何用 GDB 调试自己开发的 Node.js C++ addons?

gdb –args nodejs script.js

如何捕获 uncaughtException 并打印详细错误信息?

在进程级别捕获异常:

process.on('uncaughtException', function (e) {
  console.trace('Error: '.red + e);
  console.trace(e.stack);
  //process.exit();
});

如何优雅结束进程?

Node.js 中对接收的 POSIX 信号做自定义操作很方便,进行进程结束前的清理工作:

process.on('SIGINT', function () {
  // wait connections to close
  process.exit();
  console.log("gracefully shutting down from  SIGINT (Crtl-C)".yellow);
});

如何使用 Array 和 Object

对于列表类的信息,比如用户列表推荐使用 Object 而不是 Array:

var a = [];
a[1000] = 1;
//a is an Array which length is 1001

如何聚合多个后端服务并提供 SLA ?

用 Node.js 可以非常简单的实现对返回所用时间进行控制。比如在之前例子代码 async.parallel 的请求中设置超时定时器。对多个处理进程并发请求取其中时间最短的结果,这样可以保证返回时间都保持很短。

什么时候使用 process.nextTick() ?

  1. 重量使用 CPU 的函数中释放 CPU 给其他任务
  2. 将执行放到下一个 tick ,等待初始化

更多相关参考:

http://nodejs.org/
https://npmjs.org/
http://coffeescript.org/
http://underscorejs.org/
http://nodejs.org/api/addons.html
http://expressjs.com/
https://github.com/caolan/async
http://howtonode.org/understanding-process-next-tick
http://book.mixu.net/ch7.html
http://gruntjs.com/

目录
相关文章
|
3天前
|
JavaScript 中间件 关系型数据库
构建高效的后端服务:Node.js 与 Express 的实践指南
在后端开发领域,Node.js 与 Express 的组合因其轻量级和高效性而广受欢迎。本文将深入探讨如何利用这一组合构建高性能的后端服务。我们将从 Node.js 的事件驱动和非阻塞 I/O 模型出发,解释其如何优化网络请求处理。接着,通过 Express 框架的简洁 API,展示如何快速搭建 RESTful API。文章还将涉及中间件的使用,以及如何结合 MySQL 数据库进行数据操作。最后,我们将讨论性能优化技巧,包括异步编程模式和缓存策略,以确保服务的稳定性和扩展性。
|
1天前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js后端开发
【10月更文挑战第30天】本文将通过一个Node.js的简单示例,引导你进入Node.js的世界。我们将从基础概念讲起,然后一步步深入到代码实现,最后总结Node.js在后端开发中的优势和应用场景。无论你是前端开发者还是后端新手,这篇文章都将为你打开一扇了解Node.js的大门。
6 2
|
5天前
|
开发框架 JavaScript 前端开发
Node.js日记:客户端和服务端介绍、Node.js介绍
Node.js日记:客户端和服务端介绍、Node.js介绍
|
9天前
|
开发框架 JavaScript 前端开发
HarmonyOS UI开发:掌握ArkUI(包括Java UI和JS UI)进行界面开发
【10月更文挑战第22天】随着科技发展,操作系统呈现多元化趋势。华为推出的HarmonyOS以其全场景、多设备特性备受关注。本文介绍HarmonyOS的UI开发框架ArkUI,探讨Java UI和JS UI两种开发方式。Java UI适合复杂界面开发,性能较高;JS UI适合快速开发简单界面,跨平台性好。掌握ArkUI可高效打造符合用户需求的界面。
47 8
|
7天前
|
JavaScript 前端开发
javascript开发的简单的弹幕插件
这是一个原生javascript开发的简单的弹幕插件,具有美观、易用,占用的资源较低等特点,可以给弹幕设置内容、颜色、头像、链接地址等属性,鼠标悬停等,简单实用,欢迎下载!
26 5
|
9天前
|
JavaScript 前端开发 开发工具
Node.js——初识Node.js
Node.js——初识Node.js
14 4
|
9天前
|
JavaScript 前端开发 持续交付
构建现代Web应用:Vue.js与Node.js的完美结合
【10月更文挑战第22天】随着互联网技术的快速发展,Web应用已经成为了人们日常生活和工作的重要组成部分。前端技术和后端技术的不断创新,为Web应用的构建提供了更多可能。在本篇文章中,我们将探讨Vue.js和Node.js这两大热门技术如何完美结合,构建现代Web应用。
15 4
|
5天前
|
JavaScript 前端开发 安全
深入浅出Node.js后端开发
【10月更文挑战第26天】在这篇文章中,我们将一起探索Node.js的奇妙世界。不同于传统的Java或Python,Node.js以其异步非阻塞I/O和事件驱动的特性,在后端开发领域独树一帜。无论你是初学者还是资深开发者,这篇文章都将为你提供新的视角和思考。从基础概念到实际应用,我们一步步深入Node.js的世界,让你了解其不仅仅是JavaScript运行环境那么简单。
|
2天前
|
API 持续交付 开发者
后端开发中的微服务架构实践与挑战
在数字化时代,后端服务的构建和管理变得日益复杂。本文将深入探讨微服务架构在后端开发中的应用,分析其在提高系统可扩展性、灵活性和可维护性方面的优势,同时讨论实施微服务时面临的挑战,如服务拆分、数据一致性和部署复杂性等。通过实际案例分析,本文旨在为开发者提供微服务架构的实用见解和解决策略。
|
7天前
|
存储 JavaScript Java
后端开发的艺术:从新手到专家的旅程
在数字化时代,后端开发是构建现代应用程序不可或缺的一部分。本文将探讨后端开发的核心概念、技术栈选择、最佳实践以及如何从初学者成长为专家。我们将通过一系列实用的建议和策略,帮助读者理解并掌握后端开发的精髓,从而在这个充满挑战和机遇的领域中取得成功。