NODE的安装
网上一搜 跟着流程走一遍 就OK了
node中任何的用到的包都可以通过npm或者cnpm下载的
下载方式为npm(cnpm) i xxxx
第一天
-
创建一个简单的服务器处理get和post的数据
-
包的引入
-
http包 可用于创建一个服务器 用到的API为
http.createServer((req, res)).listen(port)
-
req
为请求是收到的请求函数 ,res
为输出的函数
let server = http.createServer(function (req, res) {}).listen(port)
- url包 用于解析所接受的url 常用的API为url.parse(url,true) 为解析url地址, 第二个参数为true时将使用查询模块分析查询字符串
let {pathname , query }=url.parse(req.url,true)
req.url
中返回正常用到的有pathname
和 query
,pathname为请求地址 query为get的数据
-
querystring包为解析字符串 常用于解析post请求的数据
-
fs是处理文件的包,如果上交的数据中有文件或者用户直接访问文件时,需要用到此包
fs.readFile(`www${req.url}`,(err,data)=>{ if (err){ res.writeHeader(404); res.write('Not Found'); res.end() }else { res.write(data) res.end() } })
readFile(url,(err,data))
函数,是读取文件函数,第一个参数是一个url,就是需要读取文件所在的地址,第二个参数一个callback
函数,返回了一个err和data,err:错位,data:数据
-
简单的get服务器
const http = require('http'); const url =require('url'); let server = http.createServer(function (req, res) { let {pathname , query} = url.parse(req.url, true)//解析出来的数据 pathname为请求地址 query为get的数据 console.log(pathname,query) }); server.listen(8888)//监听端口
-
简单的post服务器
const http = require('http'); const querystring = require('querystring'); let server = http.createServer(function (req, res) { console.log(req.method) console.log(req.url) let arr =[] req.on('data',buffer=>{//有数据进来 arr.push(buffer) }); req.on('end',()=>{//接受数据完毕 let buffer = Buffer.concat(arr)//二进制数字拼接 let post = querystring.parse(buffer.toString())//解析二进制数所转化的字符串 其实就是转化query console.log(post) }); }); server.listen(8888)//监听端口
node中处理post的数据特别麻烦,当处理post数据时需要用到两个函数,
req.on(‘data',buffer)
,和req.on('end'fn)
第一个函数是处理进来的数据buffer
在nodejs中,数据都是用流来交互的,所以要处理流处理不麻烦的数据:
let arr = []
定义一个数据变量req.on('data',buffer=>{ arr.push(buffer) })
用
arr
来装这些传进来的流req.on('end',()=>{//接受数据完毕 let buffer = Buffer.concat(arr)//二进制数字拼接 let post = querystring.parse(buffer.toString())//解析二进制数所转化的字符串 其实就是转化query console.log(post)
用
Buffer.concat(arr)
拼接流数据将流数据变成字符串
buffer.toString()
然后用quertstring包里的`querystring.parse()s解析字符串数据输出
-
简单的读取文件服务器
const http = require('http');
const fs = require('fs');
let server = http.createServer(function (req, res) {
fs.readFile(`www${req.url}`,(err,data)=>{
if (err){
res.writeHeader(404);
res.write('Not Found');
res.end()
}else {
res.write(data)
res.end()
}
})
});
server.listen(8888)//监听端口
第二天
- 理解了buffer数据处理的原理
- 服务器允许跨域请求的问题
- multiparty包更好更方便的处理数据
理解buffer的原理
直接上代码
const http = require('http');
const util = require('./buffer_util');
const fs = require('fs')
//上传文件能处理 但是文字信息就没能上传 文字信息可以用fs写入到一个txt里 这里没有写
http.createServer((req , res )=>{
let arr = [];
//获取boundary里面的内容 其实就是每个数据前的分割符
let boundary = '--'+req.headers['content-type'].split(';')[1].split('=')[1]
req.on('data',buffer =>{
arr.push(buffer);
});
req.on('end',() =>{
let buffer = Buffer.concat(arr);
//1.按照分割符切割
//利用写好的方法 传入两个 值 分别是 数据和 要切割的符号
let res= util.bufferSplit(buffer , boundary)
//去除数组的第一个和最后一个
res.pop();
res.shift();
//2.数组的每一个都处理 , 去掉每个的前面和后面
res.forEach(buffer => {
//去除了头的符号和后面符号的内容
buffer = buffer.slice(2,buffer.length-2);
//获得符号\r\n\r\n的位置
let n = buffer.indexOf('\r\n\r\n')
//获取符号前的内容 即为头部字段 可分辨是否为文件或者是文字
let info = buffer.slice(0,n).toString();
//获取四个符号后的内容 即为上传的数据
let data = buffer.slice(n+4);
//3.判定是否为文件 若是文件 则会有两段的分割号
if(info.indexOf('\r\n')!=-1){
//文件
//除去最后的分割符 然后用;来分割
let res2 = info.split('\r\n')[0].split(';');
//内容是 name = "xxx" , filename = "xxx"
//获取 name = "xxx" 里面的 "xxx"
let name = res2[1].split('=')[1];
//获取 filename = "xxx" 里的 "xxx"
let filename = res2[2].split('=')[1];
//获取 “xxx” 里的xxx
name = name.substring(1,name.length-1);
//同上 获取xxx
filename = filename.substring(1,filename.length-1);
//利用fs 生成文件 路径问upload/filename filename是你上传的文件 data是你上面处理的二进制内容
fs.writeFile(`upload/${filename}`,data,err=>{
if(err){
console.log(err);
}else{
console.log('上传成功')
}
})
}else {
//获取后面的数据 内容是 xxx = “xxx” 获取后面的“xxx” 比如name = "username"
let name = info.split(';')[1].split('=')[1];
//获取出去了“”号的内容 就是不要字符串内第一个和左后的一个
name = name.substring(1,name.length-1)
}
});
});
}).listen(8080)
exports.bufferSplit = function (buffer , delimiter) {
let arr = [];
let n = 0 ;
// 存在这个参数 !=-1 n = 这个参数的位置
while((n=buffer.indexOf(delimiter))!=-1){
arr.push(buffer.slice(0 , n));//取0到参数的内容
buffer = buffer.slice(n+delimiter.length);//取得这个参数到后面的内容
}
arr.push(buffer);//获得 除了参数为的内容(切掉参数外的内容数组)
return arr
}
服务器处理跨域问题
const http = require('http');
const querystring = require('querystring');
let allowOrigin = {
'http://localhost:8080':true,
'http://localhost:8080/?':true
}
http.createServer((req, res)=>{
let {origin}=req.headers
if(allowOrigin[origin]){
res.setHeader('Access-Control-Allow-Headers','*')//允许跨域
res.setHeader('Access-Control-Allow-Origin','*')
}
res.write('OK')
res.end()
}).listen(8888);
let origin =req.headers
是请求数据的头部,我用一个allowOrigin
json来设置可以访问我服务器的头
if(allowOrigin[origin])
如果我的json中有请求数据的头部且为true的时候
那我就用res.setHeader
来设置输出到浏览器的数据中的头部数据为可跨域
multiparty的使用
const http = require('http');
const multiparty = require('multiparty');
http.createServer((req, res)=>{
res.setHeader('Access-Control-Allow-Headers','*')//允许跨域
res.setHeader('Access-Control-Allow-Origin','*')
let form = new multiparty.Form({
uploadDir:'./upload/',
});//设置上传的文件路径
form.parse(req)
form.on('field',(name , value)=>{
console.log('字段:',name,value)
})
form.on('file',(name , file)=>{
console.log('文件:',name,file)
})
form.on('close',()=>{
console.log('表单解析完毕')
res.write('ok')
res.end();
})
}).listen(8888);
let form = new multiparty.Form({})
需要先新建一个multiparty对象
uploadDir 属性 设置上传路径 我就用了一个 需要其他路径的可以自己看文档
form.on(xxx,fn
)方法 若上传数据时文字的时候,xxx为’field’,callback
中返回两个参数(name, value),
若上传数据时文字的时候,xxx为’file’,callback
中返回两个参数(name, file),file就是文件参数
最后必须要来一个form.on('close',fn)
来关闭
第三天
websocket,fetch,jsonp集中数据交互方式的比较
- fetch–原生xhr
- jsonp–原理一个标签式的引入
- websocket–双向,性能高
fetch的基本
window.onload = function(){
let obtn = document.getElementById("Btn1")
obtn.onclick = async function() {
//1.请求数据
let res = await fetch ('data.txt')
//2.解析数据
//res内有多个函数 json text
//res.blob是解析图片 视频之类的数据
let data = await res.text()
//res.blob 之后需要用 URL.createObjectURL(data) 来解析
alert(data)
}
}
读取一个文件,研究的不多,就是了解一下
jsonp的原理
function show ({s}) {
console.log(s)
}
window.onload = function () {
let oTex = document.getElementById("oTex")
oTex.oninput = function () {
let url = `https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=${this.value}&cb=show`
let oS = document.createElement('script')
oS.src = url
document.head.appendChild(oS)
}
}
let url = `https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=${this.value}&cb=show`
这个url是百度的搜索框api接口,show是百度的方法,这个是测试出来的,别问我怎么知道
这个我定义一个show的方法,接受一个参数,然后下面代码是生成一个script标签,且src就是百度的这个api接口,而我理解的jsonp就是像引入外链接一样,最主要的特点是jsonp不需要跨域
websocket的理解
这里介绍一个websocket的包socket.io
,npm 下载即可
io.on(‘connection’,function(socket));//监听客户端连接,回调函数会传递本次连接的socket
io.sockets.emit(‘String’,data);//给所有客户端广播消息
io.sockets.socket(socketid).emit(‘String’, data);//给指定的客户端发送消息
socket.on(‘String’,function(data));//监听客户端发送的信息
socket.emit(‘String’, data);//给该socket的客户端发送消息
<script src="http://localhost:8888/socket.io/socket.io.js"></script>
<script>
let sock = io.connect('ws://localhost:8888/')
//sock.emit(name,value)
//sock.on(name,fun(value){})
sock.emit('aaa',5,12)
</script>
io.connect(ws://)这里必须要写ws,因为用到的就是ws协议
包里面有两个主要的函数,emit和on
emit是请求发出,第一个参数是请求的名字吧,可以理解为暗号,后面的参数是请求出去的数据
on是接受函数,跟emit参数一样
前端通常是用到请求,服务端用到on
下面是服务器
const http = require('http')
const io = require('socket.io')
let server = http.createServer(( req, res)=>{
}).listen(8888)
let ws = io.listen(server)
ws.on('connection',sock=>{
//socket.emit(name,value)
//socket.on(name,fun(value){})
sock.on('aaa',(a,b)=>{
console.log(a,b,a+b)
})
})
第三天
- 今天学习使用node链接数据库
先介绍一下数据库的分类
文件型:简单——access、sqlite
关系型:MySQL、Oracle
分布式:mongoDB
NoSQL:memcache、redis
这里我是用mysql的,因为开源,方便学习,在介绍一数据库的管理工具
navicat
phpmyadmin
我用的是第一个,看个人喜好
今天用的两个新的包,分别是mysql和co-mysql
Node如何操作数据库?
1.mysql模块
2.连接池
createPool
3.异步
co-mysql
上干货
-
创建数据库连接池
let conn = mysql.createPool({host:'localhost',user:'root',password:'root',database:'node'})
链接池的作用是缓冲作用,减少服务器的资源消耗,因为打开和关闭数据库等操作消耗的资源过大,创建链接池能,这里最大链接数默认10个
-
创建异步
let db = co(conn)
这样子,我们接下来的代码就可以用异步来请求数据库了
db.query这是用的最多的方法,let data =db.query(sql语句)
这样子就可以data就是从数据库获得的数据了
下面我来用一个页面的登录服务器来练习今天的知识点和温习以前的知识点
http.createServer( async (req, res)=>{
res.setHeader('Access-Control-Allow-Origin','*')//允许跨域
const { pathname , query } = url.parse( req.url , true)
if( pathname == '/reg'){
let {username , password } = query
//检查参数是否合格
let err = validator.username(query.username)
if(err){
res.write(err)
}else{
let err = validator.password(query.password)
if(err){
res.write(err)
}else{
try{
//检查用户是否存在
let data = await db.query(`SELECT ID FROM user_table WHERE username ='${username}'`)
console.log(data)
if(data.length>0){
res.write('账号已被注册')
}else{
await db.query(`insert into user_table (username , password) values ('${username}' , '${password}') `)
res.write('注册成功')
}
}
catch(e){
res.write('数据库出错了!')
}
}
}
res.end()
}else if ( pathname == '/login'){
let {username , password } = query
//检查参数是否合格
//检查用户是否存在
//检查账号密码是否配对
//返回
let err = validator.username(query.username)
if(err){
res.write(err)
}else{
let err = validator.password(query.password)
if(err){
res.write(err)
}else{
try{
let data = await db.query(`select ID,password from user_table where username = '${username}'`)
if(data.length==0){
res.write('用户名不存在')
}else if(data[0].password!=password){
res.write('密码错误')
}else{
res.write('登录成功')
}
}
catch(e){
res.write('数据库出错')
console.log(e)
}
}
}
res.end()
}else {
fs.readFile('www'+pathname, (err , buffer )=>{
if(err){
res.writeHeader(404)
res.write('not found')
}else {
res.write(buffer)
}
res.end()
})
}
}).listen(8888)
下面是html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="jquery.js"></script>
</head>
<body>
用户名: <input type="text" id="user">
密码: <input type="password" id="paw">
<input type="button" value="注册" id="reg" >
<input type="button" value="登录" id="login" >
<script>
$("#reg").click(async()=>{
let data = await $.ajax({
url:'http://localhost:8888/reg',
data:{
username :$("#user").val(),
password :$("#paw").val()
}
})
alert(data)
})
$("#login").click(async()=>{
let data = await $.ajax({
url:'http://localhost:8888/login',
data:{
username :$("#user").val(),
password :$("#paw").val()
}
})
alert(data)
})
</script>
</body>
</html>
利用jq的ajax提交数据,没用表单,直接获取dom上交,用表单的话还要处理formdata数据,有点麻烦就不用了