node 入门.

究竟是什么.

是服务器端的 js 解释器. 将改变服务器 应该如何工作的概念.

node 要解决的问题. 如何工作 如何运行一个简单的应用程序.


node 搭建博客.

express 一个MVC 架构.  npm -install -g express-generator

express -e blog 创建项目???

cd blog && npm install

这样一个博客过程就建立起来了.

可以直接在项目的根目录运行npm start或者进入bin目录直接node www都是可以的,大概看一下目录结构

目录结构

app.js 启动文件/入口文件
package.json 指定依赖模块. 之后用 install npm 会检测并自动安装所有里面指定的模块
node-modules 存放 package.json 中安装的模块.
public 存放image css js 文件
routes 存放路由文件
views 存放视图文件/模板文件
bin 存在可执行文件

app.js:  程序运行的主文件.

var express = require(“express”); var path = require(“path”); var favicon = requre(“serve-favicon”); var logger = require(“morgan”); var cookieParse = require(“cookie-parse”); var bodyParse = require(“body-parse”); // 引入各种模块

var route = require(“./routes/index”); var users = require(“./routes/users”); // 引入两个路由

var app = express(); // 实例化项目??

app.set("views", path.join(__dirname, "views")); app.set("view engine", "ejs"); // 设置 view的目录 和 模板引擎. 这里用ejs…

app.use(favicon(__dirname + "/public/favicon.ico")); // 项目的 icon app.use(logger(“dev”)); //日志记录的中间件 app.use(bodyParser.json()); // 解析 json的 中间件 app.use(bodyParser.urlencoded({ extended: false})); // 解析 url encoded 请求的中间件 app.use(cookieParser()); //解析cookie的中间件 app.use(express.static(path.join(__dirname, "public"))); // express 现在唯一的内置中间件, 静态文件存放的目录

app.use(“/”, routes); app.use(“/users”, users);
//这里就使用路由了, 其实可以在app.js里写好所有的方法,但是后面不好维护.

app.use(function(reg,res,next) { vat err = new Error(“not found”); err.status = 404; next(err); });

// error handlers

// development error handler // will print stacktrace if (app.get(‘env’) === ‘development’) { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render(‘error’, { message: err.message, error: err }); }); }

// production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { res.status(err.status || 500); res.render(‘error’, { message: err.message, error: {} }); });

module.exports = app;

接下来就可以 在 index.js 里写各种方法了

调试

一般的调试, 需要先停止 再重启. 这样很麻烦. 但是 我们可以通过一个模块来解决这个问题.

npm install -g supervisor //安装 supervisor . supervisor app.js //使用 苏泊尔visor 命令启动 app.js

中间件

类似插件: 引入就可以实现一些功能,不需你自己大费周章来实现.

页面通知 flash

php里 可以用一些 alert 之类的 来提醒用户一些信息. node/express 里 可以用 falsh功能.

crypto

一个加密算法. 内置了 md5 sha1 sha256 sha512 等算法….

首先要包含进来: crypto = require(“crypto”); var md5 = crypto.createHash(“md5”); password = md5.update(“需要加密的字符串”).digest(“hex”);

最后的 password 就是加密后的 字符串了. digest(“hex”) 作用是用 16进制格式做输出. 默认是2进制的. 会出现乱码.

multer 上传模块

资源中心

官方文档 和 github上的代码 是最好的学习资料. 最后强烈建议多阅读github上跟Node.js相关的模块的源码。

用node 搭建博客? https://howtonode.org/express-mongodb

node.js 究竟是什么:  NodeJS 文档 node入门 不长 但有思路. 深入浅出Node.js  在InfoQ上的内容 使用 Node.js 作为完整的云环境开发堆栈 七天学会NodeJS 菜鸟 : node.js 教程 NodeCloue:  Node非常受欢迎的资源,比如流行的模块·应用引擎 Node 入门教程(cn)

Node Common Module:

mongodb: NoSQL database
ejs: embeded javascript
express: A Node web framework
nodemailer: Send email using Node.js
Jade: Jade is the daddy of HTML template engines for Scala
eventproxy: An implementation of task/event based asynchronous pattern
mongoose: a MongoDB object modeling tool designed to work in an asynchronous environment.
  • express 服务端比较流行的 mvc 框架. 处理服务请求 路由转发 逻辑处理.
  • mongoose mongodb 包装 更方便的使用数据库.
  • socket.io 实现服务器和客户端的 socket 通信解决方案
  • coffee script 提高js的可读性

nodejs 工具模块

OS 模块: 基本的系统操作函数. path 模块: 处理和转换文件路径 net 模块: 底层的网络通信 DNS 模块: 解析域名 Domain 模块: 简化异常处理.

node web模块

大部分web 服务器都支持服务端的脚本语言: php python ruby 等… 并通过脚本语言从数据库获取数据.将结果返回给客户端浏览器.

最流行的 三个web服务器 apache nginx iis

web 应用构架. client 客户端: 浏览器. 可以通过http协议向服务器发送请求 server: 服务端: web 服务器: 接受客户端请求 向客户端发送响应数据. business 业务层: 通过web服务器 处理应用程序: 数据库的交互.逻辑运算.调用外部程序. data: 数据层: 一般是 数据库.

express 框架 提供一系列强大的特性 帮你创建各种 web 应用.

使用express 可以快速的搭建一个完整功能的网站. 核心特性: 可以设置中间件来响应http 请求. 定义了 路由表 用与执行不同的http请求. 可以通过向模板传递参数来动态渲染 HTML 页面.

实例:

  1. 新建 helloworld.js 文件,内容: console.log(“hello world”);

  2. 终端: node helloworld.js & 回车

  3. → hello world.

Node.js 组成:

Required 模块: 用require指令载入 node.js 模块.
创建服务器: 服务器可监听对客户端的请求.类似apache nginx.
接收&响应请求: 客户端可用浏览器或者终端来发送http请求.服务器收到请求后返回响应数据.

创建服务器

Http.createserver() 创建服务器.
Listen 方法 绑定 8888 端口.
Request Response 函数 接收和响应数据.

创建 server.js 文件,内容:

var http = require('http');    #用 require 指令引入node自带的http模块. 并赋值给 http变量

http.createServer (function (request, response) {
  #调用 http模块提供的函数: createserver 
  #函数会返回一个对象,对象有个叫 listen的方法. 
  #这个方法有个数值参数. 用来指定 http服务器监听的端口号.

  response.writeHead(  200, {"Content-Type": "text/plain"}  );
    #发送http头部; http状态值: 200 OK; 内容类型: text/plain

  response.end("Hello world\n");       #发送响应数据 hello world
}).listen(8888);

console.log("Server running at http://127.0.0.1:8888/")

# cd到目录 → 执行: node server.js → 浏览器打开 127.0.0.1:8888 → 就能看到 hello world了.

package.json

json: 管理所有项目依赖包的一个文件.
所有项目需要的依赖包.直接写在这个文件里.
然后 cd到此目录.执行 npm install 就会自动安装所有依赖包.

属性说明:

name 包名
version 版本
description 描述
homepage 官网
author 作者
contributors 贡献者
dependencies 依赖包列表

REPL (read eval print loop) 交互解释器/交互模式

终端: node & & 输入代码 & 立即查看结果. (可以很好的 调试 js代码.)

node 
> console.log('hello');
> hello  //这个就是结果.

REPL 一个环境: 可以执行以下任务:

  • 读取: 读取用户的输入. 解析输入的 js数据结构 并储存在内存中
  • 执行: 执行输入的数据结构
  • 打印: 输出结果
  • 循环: 循环遇上步骤 直到 ctrl c

终端 输入 node 就进入了 交互界面了

简单的表达式运算 1+3 回车 → 4

使用变量: 数据可以存在变量中.在你需要的时候用. var 声明. 使用var 声明的变量可以使用 console.log() 来输出变量.

x=1 回车 var y = 10 回车 x+y 回车 → 11

多行表达式:

var x = 0

do { x++; console.log(“x: “ + x); } while (x<5);

x: 1 x: 2 x: 3 x: 4 x: 5 // 这五行就是函数的结果.

REPL 命令

  • ctrl c 退出终端
  • ctrl c 两次: 退出node 环境
  • tab 列出当前命令.
  • .help 列出使用命令
  • .break 退出多行表达式
  • .clear 退出多行表达式
  • .save filename. 保存当前 会话到指定文件.
  • .load filename 载入文件.

Node 回调函数.

node.js 异步的直接体现就是回调. 异步编程基于回调来实现,但不能说 回调后程序就异步化了.

我们可以一边读取文件.一边执行其他命令. 在文件读取完成后 将文件内容作为回调函数的参数返回. 这样 在执行代码时就没有 阻塞或等待文件 i/o 操作. 大大提升了 node.js 的性能. 可以处理大量的并发请求.

阻塞代码实例: 创建一个 input.txt 内容: 0214.help

创建main.js 内容: var fs = require(“fs”);

var data = fs.readFileSync(‘input.txt’);

console.log(data.toString()); console.log(“程序执行结束”);

代码执行结果: 0214.help 程序执行结束

非阻塞代码实例 创建一个 input.txt文件 内容: 0214.help

创建main.js 代码如下:

var fs = require(“fs”); fs.readFile(‘input.txt’, function (err, data) { if (err) return console.error(err); console.log(data.toString()); });

console.log(“程序执行结果”);

代码执行结果如下: 程序执行结束 0214.help

第一个是 在文件读取完成后才执行程序. 第二个是 不需要等文件读取完 就可以读取文件的同时 执行接下来的代码.大大提升了性能.

因此: 阻塞是按顺序执行的. 非阻塞是不按顺序执行的.

node.js 事件循环

node.js 是单进程 单线程应用程序. 但是通过事件和回调支持并发.所以性能很高. node.js 每个api都是异步的. 作为一个独立的线程运行.

事件驱动程序:

当web server 接收到请求.就把它关闭 然后进行处理.然后服务下一个web请求.

当请求完成. 它被放回处理队列 当达到队列开头 这个结果就返回给用户.

node.js 有多个内置事件. 我们可以通过 events 模块. 并通过实例化 eventemitter 类来绑定和监听事件.

var events = require (‘events’); // 引入 events 模块 var eventEmitter = new events.EventEmitter(); // 创建eventemitter 对象

eventEmitter.on(“eventName”, eventHandler); // 把你的事件 及 事件的处理程序.

eventEmitter.emit(‘eventName’); // 触发事件

实例: create main.js file:

var events = require(“events”); // 引入 events 模块 var eventEmitter = new events.EventEmitter(); // 创建 eventemitter 对象

var connectHandler = function connected() { console.log (“连接成功”); //创建事件处理程序 eventEmitter.emit("data_reveived"); // 触发 data.received 事件 }

eventEmitter.on(“connection”, connectHandler); //绑定 connection 事件处理程序

eventEmitter.on('data_received', function() { // 使用匿名函数把你的 data received 事件. console.log(“数据接收成功”); });

eventEmitter.emit(“connection”); // 触发事件 console.log (“程序执行完毕”);

代码执行结果: 连接成功 数据接收成功 程序执行完毕.

node.js 工作流程

创建 input.txt 文件 . 内容: 0214.help

创建 main.js文件 内容: var fs = require(“fs”); fs.readFile(“input.txt”, function (err, data) { if (err) { console.log(err.stack); return; } console.log(data.toString()); }); console.log(“程序执行完毕”)

程序中的 fs.readfile 是异步函数 用于读取文件. 如果读取文件过程中 发生错误: err 对象 就会输出错误信息. 如果没发生错误 就跳过err 文件内容 就通过回调函数输出.

代码结果: 程序执行完毕 0214.help

我们删除input.txt 在执行代码: 结果 error: enoent, open “input.txt”

因为文件不存在.所以就输出了 错误信息.

eventemitter

node.js 里面许多对象都会发生事件. net.server 对象会在每次有新连接时分发一个事件. fs.readstream 对象会在文件被打开时发出一个事件. 所有这些产生事件的对象都是 events.eventemitter的实例.

events 模块 只提供了一个对象: events.eventemitter. eventemitter的核心就是事件触发与事件监听.

eventemitter 对象如果在实例 发生错误时候 会触发 error 事件. 当添加新的监听器时.newlistener 事件会触发. 当移除监听器时 removeListener 事件被触发.

//event.js 文件 var EventEmitter = require('events').EventEmitter;  var event = new EventEmitter();  event.on('some_event', function() {  console.log('some_event 事件触发');  });  setTimeout(function() {  event.emit('some_event');  }, 1000); 

buffer 缓冲区

js 本身 是 字符串数据类型. 没有二进制数据类型. 但是处理 tcp 流 或者文件流的时候 必须用到二进制数据. 因此就有了 缓冲区: 可以让node.js 处理二进制数据.

写入缓冲区: buf.write(string [,offset[,length]][,encoding])

string: 写入缓冲区的字符串. offset: 缓冲区开始写入的索引值. 默认0 length: 写入的字节数. 默认 buffer.length encoding: 使用的编码 默认 utf8

从缓冲区 读取数据 buf.toString([encoding[,start[,end]]]) start 开始读取的索引位置. end 结束位置. 默认为缓冲区域的末尾.

buf = new Buffer(26); for (var i=0, i<26; i++) {buf[i] = i + 97;}

console.log(buf.toString(‘ascii’)); // 输出: abcdefghijklmnopqrstuvwxyz console.log(buf.toString(‘ascii’,0,5)); // 输出: abcde console.log(buf.toString(‘utf8’,0,5)); //输出: abcde console.log(buf.toString(‘undefined’,0,5)); //使用 ‘utf8’ 编码, 并输出: abcde

buff 转为 json 对象 buf.toJSON()

var buf = new Buffer(‘www.runoob.com’); var json = buf.toJSON(buf);

console.log(json);

输出结果: [ 119, 119, 119, 46, 114, 117, 110, 111, 111, 98, 46, 99, 111, 109 ]

node.js stream 流

stream 是一个抽象的接口. 很多对象能实现这个接口. http 服务器发起请求的 request 对象是一个 stream. stdout 标准输出.

四种流类型: readable 可读操作 writable 可写操作 duplex 可读写操作 transform 操作被写入数据 然后读出结果.

常用事件: data 有数据可读时触发. end 没有更多数据可读时触发 error 接收和写入过程中发生错误时触发 finish 所有数据以被写入到底层系统时触发.

从流中读取数据:

  • 创建 input.txt 文件: 0214.help

  • 创建main.js 代码:

var fs = require(“fs”); var data = ‘’;

// 创建可读流 var readerStream = fs.createReadStream(‘input.txt’);

// 设置编码为 utf8。 readerStream.setEncoding(‘UTF8’);

// 处理流事件 –> data, end, and error readerStream.on(‘data’, function(chunk) { data += chunk; });

readerStream.on(‘end’,function(){ console.log(data); });

readerStream.on(‘error’, function(err){ console.log(err.stack); });

console.log(“程序执行完毕”);

以上代码执行结果如下: 程序执行完毕 0214.help

写入流: 创建main.js 代码:

var fs = require(“fs”); var data = ‘菜鸟教程官网地址:www.runoob.com’;

// 创建一个可以写入的流,写入到文件 output.txt 中 var writerStream = fs.createWriteStream(‘output.txt’);

// 使用 utf8 编码写入数据 writerStream.write(data,’UTF8’);

// 标记文件末尾 writerStream.end();

// 处理流事件 –> data, end, and error writerStream.on(‘finish’, function() { console.log(“写入完成。”); });

writerStream.on(‘error’, function(err){ console.log(err.stack); });

console.log(“程序执行完毕”); 以上程序会将 data 变量的数据写入到 output.txt 文件中。代码执行结果如下: $ node main.js 程序执行完毕 写入完成。 查看 output.txt 文件的内容: $ cat output.txt 0214.help

管道流:

提供了一个 输出流到输入流的机制. 通常用于从一个流中获取数据并将数据传递到另一个流中.

文件好比水桶. 水就是内容. 用一根管子 pipe 使得水从一个桶流向另一个. 这就慢慢实现了大文件的赋值过程

设置 input.txt 文件内容如下: 菜鸟教程官网地址:www.runoob.com 管道流操作实例 创建 main.js 文件, 代码如下: var fs = require(“fs”);

// 创建一个可读流 var readerStream = fs.createReadStream(‘input.txt’);

// 创建一个可写流 var writerStream = fs.createWriteStream(‘output.txt’);

// 管道读写操作 // 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中 readerStream.pipe(writerStream);

console.log(“程序执行完毕”); 代码执行结果如下: $ node main.js 程序执行完毕 查看 output.txt 文件的内容: $ cat output.txt 菜鸟教程官网地址:www.runoob.com 管道流操作实例

node.js 模块系统

为了让node.js 文件可以互相调用. node.js 提供了一个简单的模块系统. 模块是 nodejs 的基本组成部分. 文件和模块是一一对应的.

一个node.js 文件 就是一个模块. 这个文件可能是 js代码. json 或者 编译过的c扩展.

创建模块

全局对象

filename:  当前正在执行的脚本文件名.

// 输出全局变量 filename 的值 也就是当前脚本的文件名. console.log( __filename );

dirname:  当前执行脚本所在的目录. // 输出全局变量 dirname 的值 console.log( __dirname );

→ /web/com/runoob/nodejs

setTimeout(cb, ms) 多少毫秒后执行函数 cb.

function printHello(){ console.log( “Hello, World!”); } // 两秒后执行以上函数 setTimeout(printHello, 2000);

cleartimeout(f) 取消延时.

function printHello(){ console.log( “Hello, World!”); } // 两秒后执行以上函数 var t = setTimeout(printHello, 2000);

// 清除定时器 clearTimeout(t);

setinterval(cb,ms) setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。

function printHello(){ console.log( “Hello, World!”); } // 两秒后执行以上函数 setInterval(printHello, 2000); 执行 main.js 文件,代码如下所示: $ node main.js Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! …… 以上程序每隔两秒就会输出一次”Hello, World!”,且会永久执行下去,直到你按下 ctrl + c 按钮。

console

控制台的标准输出. js的调试工具. 用于向标准输出流(stdout)或标准错误流(stderr)输出字符。

  • console.log 打印字符.
  • console.error 输出错误信息
  • console.time 输出时间 计时开始
  • console.timeend 计时结束.

process 属性:

1 stdout 标准输出流。 2 stderr 标准错误流。 3 stdin 标准输入流。 4 argv argv 属性返回一个数组,由命令行执行脚本时的各个参数组成。它的第一个成员总是node,第二个成员是脚本文件名,其余成员是脚本文件的参数。 5 execPath 返回执行当前脚本的 Node 二进制文件的绝对路径。 6 execArgv 返回一个数组,成员是命令行下执行脚本时,在Node可执行文件与脚本文件之间的命令行参数。 7 env 返回一个对象,成员为当前 shell 的环境变量 8 exitCode 进程退出时的代码,如果进程优通过 process.exit() 退出,不需要指定退出码。 9 version Node 的版本,比如v0.10.18。 10 versions 一个属性,包含了 node 的版本和依赖. 11 config 一个包含用来编译当前 node 执行文件的 javascript 配置选项的对象。它与运行 ./configure 脚本生成的 “config.gypi” 文件相同。 12 pid 当前进程的进程号。 13 title 进程名,默认值为”node”,可以自定义该值。 14 arch 当前 CPU 的架构:’arm’、’ia32’ 或者 ‘x64’。 15 platform 运行程序所在的平台系统 ‘darwin’, ‘freebsd’, ‘linux’, ‘sunos’ 或 ‘win32’ 16 mainModule require.main 的备选方法。不同点,如果主模块在运行时改变,require.main可能会继续返回老的模块。可以认为,这两者引用了同一个模块。

FS 模块: 文件系统

读取文件内容的函数: 建议用异步的. 性能更高.没有阻塞.

  • 异步的 fs.readFile()
  • 同步的 fs.readFileSync()

实例 创建 input.txt 文件,内容如下: 菜鸟教程官网地址:www.runoob.com 文件读取实例 创建 file.js 文件, 代码如下: var fs = require(“fs”);

// 异步读取 fs.readFile(‘input.txt’, function (err, data) { if (err) { return console.error(err); } console.log(“异步读取: “ + data.toString()); });

// 同步读取 var data = fs.readFileSync(‘input.txt’); console.log(“同步读取: “ + data.toString());

console.log(“程序执行完毕。”); 以上代码执行结果如下: $ node file.js 同步读取: 菜鸟教程官网地址:www.runoob.com 文件读取实例

程序执行完毕。 异步读取: 菜鸟教程官网地址:www.runoob.com 文件读取

打开文件

fs.open(path, falgs[, mode], callback)

  • path 文件路径.
  • flags 打开文件的行为.
  • mode: 设置文件权限. 0666 可读写.
  • callback 回调函数. 带有两个参数: callback(err,fd)

flag 参数

r 只读模式打开文件. 文件不存在 抛出异常. r+ 读写模式打开文件. 文件不存在 抛出异常 rs 同步的方式读取文件. rs+ 同步的方式读写文件 w 写入模式 打开文件. 文件不存在就创建. wx 类似w, 文件路径不存在 这写入文件时报. w+ 读写模式打开文件. 没则新建. a 追加模式 无则新建 ax 追加 无则时报 a+ 读取追加模式打开文件. 无则创建 ax+ 文件不存在 读取追加失败.

stats 

stats.isFile() 如果是文件返回 true,否则返回 false。
stats.isDirectory() 如果是目录返回 true,否则返回 false。
stats.isBlockDevice() 如果是块设备返回 true,否则返回 false。
stats.isCharacterDevice() 如果是字符设备返回 true,否则返回 false。
stats.isSymbolicLink() 如果是软链接返回 true,否则返回 false。
stats.isFIFO() 如果是FIFO,返回true,否则返回 false。FIFO是UNIX中的一种特殊类型的命令管道。
stats.isSocket()  
写入文件: fs.writeFile(filename, data[, options], callback)
读取文件: fs.read(fd, buffer, offset, length, position, callback)
关闭文件: fs.close(fd, callback)
截取文件: `fs.ftruncate(fd, len, callback)
|*删除文件:* |fs.unlink(path, callback)  
|*创建目录:* |fs.mkdir(path[, mode], callback)`  
读取目录: fs.readdir(path, callback)
删除目录: fs.rmdir(path, callback)

node.js get/post 请求

Node.js 含有一系列内置模块,使得程序可以作为独立服务器运行.从而脱离Apache/IIS

node.js 是事件驱动的. node.js 有数十万模块.可通过npm管理器免费下载.

  脚本语言都需要一个解析器才能运行.

JS 是脚本语言. HTML 里面的JS. 浏览器就是一个解析器 (parser).  
独立运行的JS. Node.JS 就是一个解析器.  

 

解析器: 是一种运行环境. 允许js 定义各种数据结构.

  • HTML → js 用途:是操作DOM. 浏览器提供了.document之类的内置对象。

  • NodeJS中的JS的用途: 是操作磁盘文件或搭建HTTP服务器, NodeJS就相应提供了fs、http等内置对象。

Node.js 作用: 实现高性能的WEB 服务器.

js 不带IO功能. 所以开发了 node.js 来实现.

 

Mac 安装 Node.js

Node 官网下载.PKG 直接安装.

  • 測試 Node.js node -v → v0.11.16
  • 測試 npm npm -v → 2.3.0

运行 node.js

  • 打开终端:
  • 输入 node
  • 按下回车键. 就进入node了.
  • 运行代码 就直接显示结果了.

    运行大段代码:先把代码写文件里. 再node里运行这个文件.

权限问题: 监听 80 / 443 端口 需要 sudo node

或者用 chmod +s 命令.让 nodeJS 总是以 root 运行 `$ sudo chown root /usr/local/bin/node ``$ sudo chmod +s /usr/local/bin/node `

  模块: 大点的程序一般都会把程序代码 模块化. 这样使用的时候就不用加载整个程序了. 因为一般都只用到node.js里面的某几个功能

nodejs 一般把代码拆分到不同的js文件中. 每个文件 就是一个模块/文件路径就是模块名…

每个模块 都有 三个预定义好的变量可用.

  • require 使用别的模块.
    • exports 导出..
    • module

require  在当前模块 加载和使用别的模块. var foo1 = require(‘./foo’); var foo2 = require(‘./foo.js’); var foo3 = require(‘/home/user/foo’); var foo4 = require(‘/home/user/foo.js’);

可以使用以下方式加载和使用一个JSON文件。 var data = require(‘./data.json’);

exports 用于导出模块公有方法和属性。 别的模块通过require函数使用当前模块时得到的就是当前模块的exports对象。

exports.hello = function () { console.log(‘Hello World!’); };

module 访问到当前模块的一些信息.但最多的用途是替换当前模块的导出对象。例如模块导出对象默认是一个普通对象,如果想改成一个函数的话,可以使用以下方式。

module.exports = function () { console.log(‘Hello World!’); };

模块 初始化: 一个模块中的JS代码仅在模块第一次被使用时执行一次,并在执行过程中初始化模块的导出对象。之后,缓存起来的导出对象被重复利用。

主模块: 通过命令行参数传递给NodeJS以启动程序的模块被称为主模块。主模块负责调度组成整个程序的其它模块完成工作。例如通过以下命令启动程序时,main.js就是主模块。

数据流: stream. 当内存无法一次装下所需处理在数据时 或者 一边读取 一边处理更加高效时.我们 需要stream.

File system (文件系统) fs module

NodeJS最精华的异步IO模型在fs模块里有着充分的体现 support 对文件的操作.

文件属性读写 fs.stat fs.chmod fs.chown 文件内容读写 fs.readfile fs.readdir fs.writefile fs.mkdir 低层文件操作 fs.open / read / write / close.

Path ((路径) 操作文件 难免用到路径. nodejs support path module to simple it.

常用的api:

path.normalize 把传入的路径转换为标准路径.也就是 解析路径中在 . ..

如果程序需要使用 路径为某些数据的索引, 但又允许用户随意输入路径时,就需要使用该方法保证路径的唯一性。

路径: 在Windows系统下是 \ 在Linux系统下是 / 如果想保证任何系统下都使用/作为路径分隔符的话, 需要用.replace(/\/g, ‘/’)再替换一下标准路径。

多路径拼接:path.join

path.extname

当我们需要根据不同文件扩展名做不同操作时,该方法就显得很好用。以下是一个例子:
path.extname(‘foo/bar.js’); // => “.js”

遍历目录 操作文件时在 常见需求.

需要找到并处理指定目录下的所有JS文件时,就需要遍历整个目录。

递归算法: 遍历目录 一般使用这个算法. 不然很难写出简洁的代码. 递归算法: 通过不断缩小问题的规模来解决问题.

function factorial(n) { if (n === 1) { return 1; } else { return n * factorial(n - 1); } }

上边的函数用于计算N的阶乘(N!)。可以看到,当N大于1时,问题简化为计算N乘以N-1的阶乘。当N等于1时,问题达到最小规模,不需要再简化,因此直接返回1。

使用递归算法编写的代码虽然简洁, 但由于每递归一次就产生一次函数调用, 在需要优先考虑性能时,需要把递归算法转换为循环算法,以减少函数调用次数。

遍历算法:

目录是一个树状结构,在遍历时 一般用 深度优先+先序遍历算法

深度优先: 达到一个节点后.首先遍历子节点.而不是邻居节点. 先序遍历: 首次达到胃某节点就算遍历完成.而不是最后一次完成

同步遍历: 异步遍历

文本编码 常用编码: UTF8 GBK 操作最多的是文本文件.也就设计编码处理问题. 读取不同编码的文件时候,需要先将编码转为 UTF-8 才行.

GBK → UTF8 nodejs 支持在读取文件时候 转换为指定某种编码. 但是GBK不在这个范围内. 所以 只能借助 第三方包来完成: iconv-lite

单字节编码: 有时候 我们无法预知 需要读取的文件 才用哪种编码. 比如 css 有的用 gbk 有的用 UTF8 ..

如果一个文件 只包含英文字符, 那么无论用gbk/utf8 读取这个文件都是没有问题的. 因为 ascii 0-128 (范围内字符都使用相同的单字节编码.

反过来说. 如果一个文件包含中文.但是 我们要处理的字符 仅仅在 ascii 0-128 范围内(也就是说 文件由中英文组成 但是我们只需要处理英文) 那么还是可以使用单字节编码来读取文件

网络操作: 不了解网络的 coder 不是好 coder.

通过nodejs 可以编写一些 服务端程序来协助前端开发测试. 还能学习一些 http / socket 协议知识. 这些知识 在 优化前端性能/排查前端故障 时能用上.

开门红 NodeJS本来的用途是编写高性能Web服务器。 我们首先在这里重复一下官方文档里的例子,使用NodeJS内置的http模块简单实现一个HTTP服务器。

  • 终端 输入 node 回车.
  • 输入下面的代码 回车.

var http = require(‘http’); http.createServer(function (request, response) { response.writeHead(200, { ‘Content-Type’: ‘text-plain’ }); response.end(‘Hello World\n’); }).listen(8124);

浏览器 http://127.0.0.1:8124/ 就能看到….. hello world 了….

以上程序创建了一个HTTP服务器并监听8124端口,打开浏览器访问该端口http://127.0.0.1:8124/就能够看到效果。 豆知识: 在Linux系统下,监听1024以下端口需要root权限。因此,如果想监听80或443端口的话,需要使用sudo命令启动程序。

网络 API: HTTP module

  • 作为服务端使用时: 创建一个HTTP服务器,监听HTTP客户端请求并返回响应。

  • 作为客户端使用时: 发起一个HTTP客户端请求,获取服务端响应。

    服务器模式简介:(上面的例子) var http = require(‘http’); http.createServer(function (request, response) { response.writeHead(200, { ‘Content-Type’: ‘text-plain’ }); response.end(‘Hello World\n’); }).listen(8124);

.createserver 创建一个服务器. .listen 监听端口. 每当来了一个客户请求,创建服务器时传入的回调函数就被调用一次。可以看出,这是一种事件机制。

http 请求本质: 请求头 headers +请求体body 组成 完整的 http 请求数据内容: POST / HTTP/1.1 User-Agent: curl/7.26.0 Host: localhost Accept: / Content-Length: 11 Content-Type: application/x-www-form-urlencoded

Hello World 空行之上是请求头,之下是请求体。

Http 响应本质 也是一个数据流. 也由 header + body 组成. HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 11 Date: Tue, 05 Nov 2013 05:31:38 GMT Connection: keep-alive

Hello World

HTTPS module 和http 差不多. 但是 需要额外处理 SSL 证书.

URL module 处理http 时候 url 模块使用率超高. url 模块 允许 解析 url/生成 url / 拼接 url.

url 组成:

                      href ---- 
                        host              path
                  --------------- ----------------------------  http: // user:pass @ host.com : 8080 /p/a/t/h ?query=string #hash ----  protocol     auth     hostname   port pathname     search     hash
                                            ------------
                                               query

Net  创建 socket 服务器 或者客户端. socket 在前端设计的不多.

进程管理: NodeJS可以感知和控制自身进程的运行环境和状态,也可以创建子进程并与其协同工作,这使得NodeJS可以把多个程序组合在一起共同完成某项工作,并在其中充当胶水和调度器的作用。

Example: 拷贝 一个目录下的 所有文件 和 子目录 到另外一个目录.

自己写的话 要写不少代码.
用终端的话 cp 一条命令就搞定了.

如何用 nodejs 调用终端来简化 目录拷贝.

var child_process = require(‘child_process’); var util = require(‘util’);

function copy(source, target, callback) { child_process.exec( util.format(‘cp -r %s/* %s’, source, target), callback); }

copy(‘a’, ‘b’, function (err) { // … });

process 任何一个进程 都有启动进程时 使用的命令行参数. 有标准的输入输出. 有运行权限.有运行环境.运行状态. nodejs 中 可以用 process 对象感知和控制 nodejs 自身进程的方方面面. process 不是内置模块 而是一个全局对象.任何地方都能使用.

child process 创建+控制 子进程

退出程序: 一个程序 做完所有事情后 就正常退出. 这时候退出状态码为0. 程序运行异常.挂了 这时候 退出状态码 就不是0 了. 如果代码中 捕获了某个异常.觉得程序不应该继续运行下去.需要立即退出.并且把状态码指定某个数字

try { // … } catch (err) { // … process.exit(1); }  

控制输入输出 标准输入流: stdin → process.stdin 标准输出流: stdout → process.stdout 标准错误流: stderr → process.stderr

异步编程 nodejs 最大的卖点 事件机制 和 异步IO. 没有掌握异步编程 就不能说真正学会了 nodejs.

回调 异步编程 直接体现的就是回调. js 本身是单线程运行的.不可能一段代码还没结束 就去执行别的代码.

如果某个函数做的事情是创建一个别的线程或进程,并与JS主线程并行地做一些事情,并在事情做完后通知JS主线程,那情况又不一样了。

Domain domain module. 简化异步代码的异常处理. 一个域就是一个js运行环境. 如果一个异常没有被捕获.将作为一个全局异常被抛出。