以前学习C、OC、Swift、H5的时候都没有留下痕迹,心里甚是遗憾,最近用Nodejs参与了一个web开发,果断留个纪念,供日后瞻仰。。。
菜鸟教程:http://www.runoob.com/nodejs/nodejs-install-setup.html
Github:https://github.com/Zyj163/Node.JS_learning(笔记,非demo)
环境配置:
方式一:http://nodejs.org下载安装(我用的这个)
方式二:使用终端(网上介绍的,没实验。。。)
1.安装home-brew
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)
2.安装node
brew install node
当安装Node时会同时安装npm,npm是Node开发包管理器,用法省略。。。
使用:
先来一个Hello World
创建一个helloWorld.js的文件(我用的编辑器是webStorm)
var http = require('http');
http.createServer(function(req,res){
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
res.writeHead(200, { 'Content-Type': 'text/plain' });
// 发送响应数据 "Hello World"
res.end('Hello world!');
}).listen(3000);
console.log('Server started on localhost:3000; press Ctrl-C to terminate....');
打开终端,cd到当前目录,node hello World.js,然后打开浏览器访问http://localhost:3000即可
推荐一个好东西sudo npm install -g supervisor,cd到当前目录supervisor helloWorld.js,这样就不需要每次修改后台代码后,重启服务了,退出Ctrl+c
Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。Node 所有 API 都支持回调函数。
Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发。
Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。
Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.
Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。引用runoob中的一张图
EventEmitter
Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件
// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);
// 触发事件
eventEmitter.emit('eventName','arg1','arg2');
//移除指定事件的一个已经注册的监听器
eventEmitter.removeListener('eventName',eventHandler);
//移除指定事件的所有监听器
eventEmitter.removeAllListeners('eventName');
EventEmitter 对象如果在实例化时发生错误,会触发 'error' 事件。当添加新的监听器时,'newListener' 事件会触发,当监听器被移除时,'removeListener' 事件被触发。可以给同一事件创建多个监听,会被先后调用。
大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。 包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。
Buffer(缓冲区)
在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。
//方法 1
//创建长度为 10 字节的 Buffer 实例:
var buf=newBuffer(10);
//方法 2
//通过给定的数组创建 Buffer 实例:
var buf2=newBuffer([10,20,30,40]);
//方法 3
//通过一个字符串来创建 Buffer 实例:
var buf3=newBuffer("www.runoob.com","utf-8");
/*写入
buf.write(string[, offset[, length]][, encoding])
参数
参数描述如下:
string - 写入缓冲区的字符串。
offset - 缓冲区开始写入的索引值,默认为 0 。
length - 写入的字节数,默认为 buffer.length
encoding - 使用的编码。默认为 'utf8' 。
* */
var len=buf.write('www.runoob.com');
console.log('写入字节数:'+len);
/*读取
buf.toString([encoding[, start[, end]]])
参数
参数描述如下:
encoding - 使用的编码。默认为 'utf8' 。
start - 指定开始读取的索引位置,默认为 0。
end - 结束位置,默认为缓冲区的末尾。
* */
var re=buf.toString();
//转为json对象
var json=buf.toJSON(buf);
//合并buffer
var buf4= Buffer.concat([buf,buf3]);
/*拷贝
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])
参数
参数描述如下:
targetBuffer - 要拷贝的 Buffer 对象。
targetStart - 数字, 可选, 默认: 0
sourceStart - 数字, 可选, 默认: 0
sourceEnd - 数字, 可选, 默认: buffer.length
* */
var buf5=newBuffer(10);
buf5.copy(but);
Stream(流)
Stream 对象都是 EventEmitter 的实例(对http 服务器发起请求的request 对象就是一个 Stream,所以request也有下面的事件)。常用的事件有:
data - 当有数据可读时触发。
end - 没有更多的数据可读时触发。
error - 在接收和写入过程中发生错误时触发。
finish - 所有数据已被写入到底层系统时触发。
从流中读数据:
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);
});
写入流:
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("程序执行完毕");
管道流:
var fs= require('fs')
var zlib= require('zlib')
//压缩
fs.createReadStream('input.txt')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('input.zip'))
//解压
fs.createReadStream('input.zip')
.pipe(zlib.createGunzip())
.pipe(fs.createWriteStream('input.txt'))
模块系统:
1、提供函数:
定义:
exports.world = function() {}
使用:
var use = require('./world');
use.world();
2、提供对象:
定义:(fuc外面的东西可以理解为私有的,里面的是公开的)
function Hello() {
var name;
this.setName = function(thyName) {
name = thyName;
};
this.sayHello = function() {
console.log('Hello ' + name);
};
};
module.exports = Hello;
使用:
var Hello = require('./hello');
hello = new Hello();
hello.setName('BYVoid');
hello.sayHello();
路由:
解析URL,引用url和querystring模块
全局对象与全局变量:
__filename 表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。 如果在模块中,返回的值是模块文件的路径。
__dirname 表示当前执行脚本所在的目录。
process.memoryUsage() 输出内存使用情况
常用工具:
util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数。JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同。JavaScript 没有 提供对象继承的语言级别特性,而是通过原型复制来实现的。
var util= require('util');
functionBase(){
//不能继承
this.name='base';
this.base=1991;
this.sayHello=function(){
console.log('hello'+this.name);
}
}
//可以被继承
Base.prototype.showName=function(){
console.log(this.name);
};
functionSub(){
this.name='sub';
//Sub 仅仅继承了Base 在原型中定义的函数,而构造函数内部创造的 base 属 性和 sayHello 函数都没有被 Sub 继承。
}
util.inherits(Sub,Base);
varobjBase=newBase();
objBase.showName();
objBase.sayHello();
console.log(objBase);
varobjSub=newSub();
objSub.showName();
console.log(objSub);
util.inspect(object,[showHidden],[depth],[colors])是一个将任意对象转换 为字符串的方法,通常用于调试和错误输出。它至少接受一个参数 object,即要转换的对象。
更多详情可以访问 http://nodejs.org/api/util.html 了解详细内容
可以使用typeof some ==='function' 做类型判断
文件系统:
应该很多都需要知道,没必要截了http://www.runoob.com/nodejs/nodejs-fs.html
知道这些基础知识差不多就可以进行下一个目标express了,这个才是重点!!