node入门
## node
1. 以前我们打代码只能在浏览器里面显示效果，谷歌浏览器的控制台事实上就是V8引擎的界面，浏览器有窗口去看到页面效果

2. nodejs环境就是一个脱离浏览器运行的V8引擎，它是没有显示页面的窗口

## 客户端 浏览器端
HTML
```javascript
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
	</body>
	<script src="nodejs.js"></script>
</html>
```
JS 它如果不在HTM中嵌入，那这个脚本作用为零L
```javascript
var a = 1;
setInterval(function() {
	console.log(a);
	a++
}, 1000)
```

## 服务器端 nodejs
```javascript
var a = 1;
setInterval(function() {
	console.log(a);
	a++
}, 1000)
```
在node命令行里面执行
```
node nodejs.js
```

## 浏览器引入多个JS的时候
```javascript
	<script src="nodejs.js"></script>
	<script src="module.js"></script>
```

## 服务端因人员多个JS的时候
```javascript
	require("./nodejs.js");
	require("./module.js");
```

## 原生模块
```
//带路径的自定义模块(服务)
var module = require("./module.js");
//不带路径的原生模块
var http = require("http");
```

## 创建服务器的步骤
接下来我们使用 http.createServer() 方法创建服务器，并使用 listen 方法绑定 8888 端口。 函数通过 request, response 参数来接收和响应数据。
1. 引入http模块
```javascript
var http = require("http");
```

2. 接下来我们使用 http.createServer() 方法创建服务器，并使用 listen 方法绑定 8888 端口。 函数通过 request, response 参数来接收和响应数据。
```javascript
http.createServer(function(request,response){
	//改写头部，允许跨域
	response.setHeader('Access-Control-Allow-Origin','*');
	var obj = {
		name:'wscats',
		age:88
	}
	response.end(JSON.stringify(obj))
}).listen(12345)
```
3. 打开服务器
```
node xxx-server.js
```

## nodejs获取前端传过来的数据
```javascript
$_GET['']
$_POST['']
```

```javascript
var url = require("url");
var querystring = require("querystring")
var paramsStr = url.parse(request.url).query
var params = querystring.parse(paramsStr)//$_GET['']
```

## 回调函数
回调函数其实是解决异步编程的重要方法
因为异步是脱离了主线程的，回调可以让异步程序在执行完的时候触发某个方法，从而把它的逻辑带回到主线程

1. 浏览器端出现这三个都是异步方法 ajax setTimeout setInterval

## ajax
```javascript
console.log("start");

		function ajax(callback) {
			var xmlhttp = new XMLHttpRequest();
			xmlhttp.open("GET", "../test.php", true);
			xmlhttp.send();
			xmlhttp.onreadystatechange = function() {
				if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
					callback(xmlhttp.responseText);
				}
			}
		}
		ajax(function(data) {
			console.log(data)
			console.log("end")
		})
```

## 定时器
```javascript
console.log("start")
var a = 1;

function cb(callback) {
	setTimeout(function() {
		a = 2;
		//console.log(a)
		callback()
	}, 1000)
}
cb(function(){
	
	console.log(a)
})
```

## fs读写文件
读写文件的方法
> read 异步
> readSync 同步
> xxxSync就是同步方法

同步阻塞
```javascript
var fs = require("fs");
console.log("start")
//同步读取
var data = fs.readFileSync("demo.txt");
console.log(data.toString())
console.log("end")
```
这样会输出 start->adcd->end
这里面会一直等到txt文件完全读完，才往下执行

异步非阻塞
```javascript
var fs = require("fs");
console.log("start")
//异步读取
fs.readFile("demo.txt", function(err, data) {
	console.log(data.toString())
})
console.log("end")
```
这样会输出 start->end->adcd
这里面会不会等到txt文件完全读完，会一直往下走，知道txt读完再执行相应回调执行对应的逻辑

## 事件驱动
其实就是为了解决多层回调(回调地狱)
把异步编程，用同步的方式去编写，便于维护
eventEmitter.on()方法注册事件
eventEmitter.emit()方法广播事件
```javascript
// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
eventEmitter.on('event1', function() {
	setTimeout(function() {
		console.log("1")
		eventEmitter.emit('event2');
	}, 1000)
});
eventEmitter.on('event2', function() {
	setTimeout(function() {
		console.log("2")
		eventEmitter.emit('event3');
	}, 1000)
});
eventEmitter.on('event3', function() {
	setTimeout(function() {
		console.log("3")
	}, 1000)
});
//触发事件1
eventEmitter.emit('event1');
```

## 读写流
跟fs readFile和writeFile相比，读写流是分一部分一部分地写，readFile和writeFile一次性写入，所以在处理大型文件的时候一般用流的形式读或者写
```javascript
var data = '';
// 创建可读流
var readerStream = fs.createReadStream('test.txt');
// 处理流事件 --> data, end, and error
readerStream.on('data', function(chunk) {
   data += chunk;
});
readerStream.on('end',function(){
   console.log(data);
});
```

```javascript
var data = '菜鸟教程官网地址：www.runoob.com';
// 创建一个可以写入的流，写入到文件 output.txt 中
var writerStream = fs.createWriteStream('news.txt');
writerStream.write(data,'UTF8');
// 处理流事件 --> data, end, and error
writerStream.on('finish', function() {
    console.log("写入完成。");
});
```

## 管道流
一般是用于copy文件，可以是img，video,txt等文件，一般用于下载
```javascript
var fs = require("fs");
// 创建一个可读流
var readerStream = fs.createReadStream('./video/1.avi');
// 创建一个可写流
var writerStream = fs.createWriteStream('./video/11.avi');
readerStream.pipe(writerStream);
```

## 链式流
```javascript
//链式流
fs.createReadStream('./video/1.avi')
//.pipe(fs.createWriteStream('./video/11.avi'))
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('./video/video.avi.gz'));
```

## API文档
[NodeJS Api文档](http://nodejs.cn/api)

## 模块
引入模块的方法就是
```javascript
var fs = require("fs");
```
定义模块的方法
```javascript
var obj = {
	name:'w'
}
module.exports = obj;

```
## 三种模块类型
内置模块 fs http url querystring

fs:操作文件的 http:创建服务器或者发送请求

url:处理路由的 querystring:处理字符串
```javascript
var fs = require("fs");
//第三方模块 
//cnpm install XXX
var jquery = require("jquery")
//自定义模块
var fss = require("./fs")
```

## CMD命令
```
cd 定位到文件夹
dir 查看目录
mkdir 新建文件夹
```

## express框架
新建一个package.json,存放着我们模块的信息
```
npm init
```
安装express框架
```
npm install express
```

## jade模板引擎
```
//views, 放模板文件的目录，比如： 
app.set('views', './views')
//view engine, 模板引擎
app.set('view engine', 'jade')
```
```
npm install jade
```

###express前后端分离
后端
前后端分离那就是后端只负责提供数据
```javascript
var express = require("express");
var app = express();
//REST post get put delete
app.get("/", function(req, res) {
	res.append("Access-Control-Allow-Origin", "*");
	res.send("hello")
})
app.listen(8899)
```
>前后端分离关键的一环就是用ajax或者jsonp或者表单提交，来通信数据

前端负责拿数据并且渲染
前端
```javascript
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<p></p>
	</body>
	<script src="../js/jquery.js"></script>
	<script>
		$.ajax({
			type:"get",
			url:"http://localhost:8899/",
			async:true,
			success:function(data){
				console.log(data)
				$("p").html(data)
			}
		});
	</script>
</html>
```
优点:方便维护，简化了后端的工作，会更专注各自的工作，细化了工作流程
缺点:不利于SEO的优化，不方便爬虫

## express 前后端不分离
后端
```javascript
var express = require("express");
var app = express();
//REST post get put delete
app.get("/", function(req, res) {
	res.append("Access-Control-Allow-Origin", "*");
	var html = `
	<!DOCTYPE html>
	<html>
		<head>
			<meta charset="UTF-8">
			<title></title>
		</head>
		<body>
			<header>hello后端渲染</header>
			<p></p>
		</body>
		<script src="http://localhost:81/angular/0410/express/js/jquery.js"></script>
	<script>
		$.ajax({
			type:"get",
			url:"http://localhost:8899/data",
			async:true,
			success:function(data){
				console.log(data)
				$("p").html(data)
			}
		});
	</script>
	</html>
	`
	res.send(html)
})
app.get("/data", function(req, res) {
	res.send("hello前端渲染")
})
app.listen(8899)
```
优点:有利于SEO的优化
缺点:不方便维护，后端工作量就很大，不利于实现一些用户的交互效果


## websocket
ws websocket 基于TCP/IP全双共通信协议 长连接

http ajax 短链接

ftp file://文件协议

```
			ws = new WebSocket("ws://loacalhost:7272");
			//打开WebSocket进行握手
			ws.onopen = function(){
				//第一次连接时候触发的回调
			}
			//服务端通信给你的消息
			ws.onmessage = function(){
				//连接成功后一直监听的回调函数
			}
			//服务端关闭时候触发的回调
			ws.onclose = function(){
				// 关闭 客户端关闭/服务端关闭
			}
			//出现错误时候的回调
			ws.onerror = function(){
				
			}
			//向websocket服务端发送数据
			ws.send()
```

## socket.io
安装socket.io第三方模块
```
npm install socket.io
```
客户端文件引入的JS
```
<script src="https://cdn.socket.io/socket.io-1.4.4.js"></script>
```
websocket是不会跨域的，ajax是会跨域的
websocket是长连接，如果你不关掉浏览器或者终止连接，或者不关掉服务器，它是永远保持着连接的
ajax是短连接，成功后就更服务器脱离关系