《了不起的Node.js》读后笔记

介绍:

主要介绍五部分:Node核心设计理念、Node核心模块APIWeb开发、数据库以及测试。

2009Ryan Dahl着手开发Node.jsNode以其异步IO、服务器端JavaScript的特点为Web开发掀开了新的篇章。

Node.js快速高效的优点得益于一种叫做事件轮询(event loop)的技术,以及其构建于V8之上V8GoogleChrome Web浏览器设计的JavaScript解释器和虚拟机,它运行JavaScript非常快。


Part 1 从安装与概念开始


1 安装

Node REPL

要运行NodeREPL,在终端输入node即可。

执行文件:

Node.js可以通过node命令来执行Node脚本。

NPM

Npm search 模块名:进行搜索模块


2 JavaScript概述

JavaScript是基于原型、面向对象、弱类型的动态脚本语言。

V8中的JavaScript:

Object.keys():获取对象上所有的自有键;

Array.isArray():检查是否是数组;

数组方法:forEachmap

字符串方法:trim();

JSONJSON.stringifyJSON.parse

FUNCTION#BIND

FUNCTION#NAME

_PROTO_(继承);

存储器:_defineGetter__defineSetter_


3 阻塞与非阻塞IO

NodeApache的区别在于基础架构上,Node采用一个长期运行的进程,相反,Apache会产出多个线程(每个请求一个线程),每次都会刷新状态。


阻塞:

Node.js使用了事件轮询,因此setTimeout是非阻塞的。所有像httpnet这样的原生模块中的IO部分也都采用了事件轮询技术。


Node.js又是如何做到高并发的呢?

为了搞清楚这个问题,首先要明白调用堆栈的概念。当v8首次调用一个函数时,会创建一个众所周知的调用堆栈或者称为执行堆栈。

关键在于,在调用堆栈执行非常快的情况下,同一时刻你无需处理多个请求。这也是为何说v8搭配非阻塞IO是最好的组合:v8执行JavaScript速度非常快,非阻塞IO确保了单线程执行时,不会因为有数据库访问或硬盘访问等操作而导致被挂起。

在我们的应用中,常见的IO例子就是从数据库中获取数据。


错误处理:

Node应用依托在一个拥有大量共享状态的大进程中。

除了uncaughtExceptionerror事件外,绝大部分Node异步API接收的回调函数,第一个参数都是错误对象或者null


4 Node中的JavaScript

Node.js中写JavaScript和在浏览器中写JavaScript截然不同。Node.js除了提供和浏览器一样的基本语言之外,还在语言基础上提供了构建了强大网络应用所需的API


global对象:

Global:和window一样,任何global对象上的属性都可以被全局访问到;

Process:所有全局执行上下文中的内容都在process对象中;


process.nextTick函数可以将一个函数的执行时间规划到下一个事件循环中。


模块系统:

Node摒弃了采用定义了一堆全局变量的方式,转而引入了一个简单但却无比强大的模块系统,该模块系统有三个核心的全局对象:requiremoduleexports


事件:

Node中,你也希望可以随处进行事件的监听和分发,为此,Node暴露了Event EmitterAPI,该API上定义了onemit以及removeListener方法。它以process.EventEmitter形式暴露出来。

当用户提交表单时,你通常会监听请求的dataend事件。


buffer

Buffer是一个表示固定内存分配的全局对象,它就好比是一个由八位字节元素组成的数组,可以有效地在JavaScript中表示二进制数据。



Part 2 Node重要的API


5 命令行工具(CLI)以及FS API:首个Node应用

fs模块是唯一一个同时提供同步和异步API的模块。

console.log(require(‘fs’).readdirSync(‘.’));

异步版本:Function async(err,files){console.log(files);}

require(‘fs’).readdir(‘.’,async);


流:

Process全局对象中包含了三个流对象,分别对应三个UNIX标准流:

Stdin—标准输入;

stdout—标准输出;

stderr—标准错误;


输入和输出:

Process.stdin.resume();等待用户输入

process.stdout.write(‘haha’);输出

stdin.on(‘data’,option);监听用户输入的数据


Argv:

process.argv包含了所有Node程序运行时的参数值。


工作目录:

在此前的例子中,我们使用__dirname来获取执行文件时该文件在文件系统中所在的目录。

Process.cwd():获取当前工作目录;

Process.chdir():更换工作目录;


环境变量:

Node允许通过process.env变量来轻松访问shell环境下的变量。


退出:

要让一个应用退出,可以调用process.exit并提供一个退出代码。


信号:

进程和操作系统进行通信的其中一种方式就是通过信号。


fs模块:

fs.createReadStream方法允许为一个文件创建一个可读的Stream对象。


监视:

除了fs.watchFile之外,还可以使用fs.watch来监视整个目录。



6 TCP

TCP是一种传输层协议,它可以让你将数据从一台计算机完整有序地传输到另一台计算机。

Node HTTP服务器是构建于Node TCP服务器之上的。从编程角度来说,也就是Node中的http.Server继承自net.ServernetTCP模块的)。


Telnet

Telnet是一个早期的网络协议,旨在提供双向的虚拟终端。


当底层套接字关闭时,Node.js会触发close事件。Node.js中有两个和连接终止相关的事件:endclose


IRC是因特网中继聊天(Internet Relay Chat)的缩写,它也是一项常用的基于TCP的协议。


7 HTTP

HTTP协议构建在请求和响应的概念上,对应在Node.js中就是由http.ServerRequesthttp.ServerResponse这两个构造器构造出来的对象。


Node.js提供了一个称为querystring的模块,可以方便地对查询字符串进行解析,这样,我们就可以像处理头信息一样对其进行处理。


和创建一个TCP客户端类似,通过http模块中的request静态方法创建一个Client对象,来创建一个客户端。


有一个叫做superagent的模块扩展response对象。


使用up重启HTTP服务器:up -watch -port 80 server.jswatch意味着up会通过Node API来监听该目录下所有文件的更改)。



Part 3 Web开发

8 Connect

Connect是一个基于HTTP服务器的工具集,它提供了一种新的组织代码的方式来与请求、响应对象进行交互,称为中间件。

Node中的全局变量__dirname来获取当前服务器所在的路径。


主要有:static中间件、query中间件、logger中间件、body.parser中间件、cookie、会话(session)、Redis.sessionmethodOverride中间件、basicAuth中间件

session默认的存储方式就是内存。


9 Express

鉴于Connect基于HTTP模块提供了开发Web应用常用的基础功能,Express基于Connect为构建整个网站以及Web应用提供了更为方便的API


Ejs一个模版引擎:

JavaScript代码嵌在<%%> EJS标签中,另外,我们通过在<%之后加入“=”符号将变量值打印出来。


创建express应用:

var express = require(‘express’);

Var app = express.createServer();

可以调用set方法设置配置信息。


定义路由:

通过使用Express来定义路由就无须手动地每次去检查methodurl属性,只需调用Express提供的对应HTTP method的方法,并将URL和对应的处理中间件传递进去就可以了。

Expressresponse对象提供了render方法。


模版引擎:

除了ejs,还有其他模版引擎可以在express中使用:HallJadeCoffeeKupjQuery Templates for node


快捷方法:

ExpressNode中的RequestResponse对象提供了一系列扩展来简化开发。

Request对象上的扩展如下:

headeracceptsis

Response对象上的扩展如下:

headerrendersendjsonredirect


代码组织策略:

对于任意一个Node.js应用来说,第一条准则都是模块化。Node.js通过提供一个简单的require API来提供一个强大的代码组织策略。


使用Express最大的益处就在于,它简洁、配置少但却又不失灵活,同时它和Connect一样构建于测试全面、抽象简洁的基础之上。

和其他Web框架或者类库不同,Express非常容易进行模块化来满足不同的需求、结构以及模式。


10 WebSocket

websocketweb下的TCP

每次提到WebSocket的时候,其实是在讲两部分内容,一部分是浏览器实现的WebSocket API,另一部分是服务器端实现的Websocket协议。

它和HTTP之间主要的区别就是,握手完成后,客户端和服务器端就建立了类似TCP socket这样的通道。


11 Socket.IO

Socket.IO最诱人的特性之一就是消息的传递是基于传输的,而非全部依靠WebSocket,也就是说,Socket.IO可以在绝大部分的浏览器和设备上运行,从IE6IOS都支持。


当连接丢失时,Socket.io默认会自动重连。


如果通过主流浏览器来连接Socket.IO服务器,那么Socket.IO就会使用WebSocket来通信。Socket.IO总会尝试选择对用户来说速度最快、对服务器性能来说最好的方法来建立连接,要是条件达不到,那么首先会保证连接正常。


socket.broadcast.emit中的broadcast是一种标志信息,它改变了emit函数的行为。


Part 4 数据库


12 MongoDB

MongoDB是一个面向文档,schema无关(schema-less)的数据库,它非常适合于Node.js应用以及云端部署。

Mysql是根据固定的结构设计(schema)将数据存储在表中不同,MongoDB可以将任意类型的文档数据存储到集合中(schema无关),这也是mongodb最有意思的特性之一。

MongoDB中,可以将数据都看作文档,其设计非常灵活。


MongoDB还有一个非常重要的特性,能够将其与其他键值形式的NoSQL数据库区别开来,就是文档可以是任意深度的。

Npm引入mongoldb


Mongoose

可以简化查询方式,是一个Node.js模块,它为MongoDBJavaScript提供了传统关系型数据库ORM的部分功能。


通过Node.js操作MongoDB文档数据最主要的方式就是通过驱动器(driver)。通常在Node.js中驱动器指的就是一些基本的API,它懂得数据库网络层协议和其通信,并知道如何编码和解码存储的数据。


连接数据库:

Var server = new mongodb.Server(’127.0.0.1’,27017);

new mongoldb.Db(‘my-website’, server).open(function(err, client){});

建立集合:

app.users = new mongoldb.Collection(client, users’);

插入文档:

App.users.insert(req.body.user,function(err, doc){});

查询文档:

MongoDB有一个ensureIndex命令,不管索引是否存在,都可以调用这个命令来确保在查询前建立了索引。

insert命令一样,findOne命令可以对MongoDB进行查询文档的操作。


校验:

Mongoose通过允许在应用层定义schema来解决校验的问题,它在保持文档灵活性和易改动的前提下,引入了特定的属性对其做一定的约束,称为模型。


原子性:

要确保某个操作的原子性,MongoDB提供了$set$push这样不同的操作符。


Mongoose

连接数据库:

mongoose.connect(‘mongoldb://localhost/my_database);

Var Schema = mongoose.Schema;

Var postschema = new Schema({

title: String,

body: String,

date: Date

});

创建好schema后,通过mongoose来注册一个模型:

Var post = mongoose.model(‘blogpost’, postschema);   //blogpost是集合名


索引是在MongoDB数据库中确保快速查询的重要因素。


13 Mysql

一个原生的MySQL驱动器(一个名为node-mysql的项目),通过node-mysql,我们可以书写自己的SQL查询语句来操作数据库。

除了驱动器,本章还会介绍MySQL的对象关系映射器ORM—node-sequelizeORM提供了一个Mysql数据库中数据到JavaScript模型对象的映射,使得操作数据关系、数据处理变得更加容易。


Node-mysql提供的执行查询语句的API非常简单:client.query(<sql>,<callback>)。关闭连接的APIclient.end


14 Redis

Redis是一种数据库,不过更准确地来说,它更像一台结构化的数据服务器,从定义上来说相比Mysql更接近MongoDB

和操作表中的行或者集合中的文档不同,在Redis中是通过键来访问数据的。

Redis支持的数据类型:字符串、列表、数据集、哈希、有序数据集。

RedisMongoDB最显著的不同点就是,Redis中的文档结构总是扁平的,不能包含像MongoDB支持的那种嵌套的数据结构。


数据类型:

字符串:Redis中的字符串类似于JavaScript中的NumberString

哈希:在redis中,哈希类似于子对象;

列表:Redis中的列表就等同于JavaScript中的字符串数组。

数据集:

有序数据集;


Part 5 测试

15 代码共享

书写兼容的Javascript

一些主流浏览器的特性在其他浏览器及js引擎中都没有,要想让代码处处运行,通过扩展原型来提供这类功能的实现或者使用工具函数。


16 测试

书写测试代码时,目标就是要断言条件是否通过,不通过就抛出异常。

Mocha

Mocha是一个测试框架,简化了书写测试代码的过程,提供划分测试集、运行并同时输出有助于开发者理解的结果页。

BBD风格:行为驱动开发;

TDD风格:测试驱动开发,它和BDD类似,但是组织方式是使用测试集和测试。








猜你喜欢

转载自blog.csdn.net/u012755393/article/details/80271076