Node学习
1.提示信息
cnpm install --save-dev @types/node
npm config set registryhttps://registry.npm.taobao.org
2.Node中的JavaScript
- EcmaScript
- 没有 DOM 、BOM
- 核心模块
- 第三方模块
- 用户自定义模块
核心模块
Node为服务器提供了很多服务器级别的API,这些API被包装到一个具名的核心模块中。
eg :fs
http
path
os
var fs = require('fs');
3.代码规范
JavaScript Standard Style
-
缩进两空格
-
字符串使用单引号
-
使用全等于
===
-
关键字,函数名后加空格
-
一定处理回调传回来的
err
参数 -
不用写分号 以
(
[
` 开头的需要前面加分号 -
······
4.http服务
1.创建Server
var http = require('http')
2.监听 Server 的 request 请求事件,设置请求处理函数
一个请求对应一个响应
server.on('request', function(req,res){
var url = req.url
if (url === '/'){
res.end('hello world')
}else {
res.end('404')
}
})
3.绑定端口号,启动服务
server.listen(3000,function(){
console.log('running...')
})
4.文件的访问
- 引入
fs
模块
var fs = require('fs')
- 读取文件
fs.readFile('C:/Users/zhangan/Desktop/hello/demo.html',function(err,data){
if(err) {
//这里的return 不是为了返回值 而是阻止代码继续执行
return res.end('404 Not Found')
}
res.end(data)
})
- 处理乱码问题
Content-Type
res.setHeader('Content-Type','text/plain; charset=utf-8')
res.end(data)
- 如何像Apache服务器那样简单的访问文件
var url = req.url
var filePath = '/index.html'
if (url !== '/'){
filePath = url
}
// console.log(wwwDir + filePath)
fs.readFile(wwwDir + filePath, function(err, data){
if (err){
return res.end("404 Not Found")
} else {
res.end(data)
}
})
5.处理静态资源
-
用到
url
模块中的 parse 方法将路径解析为一个方便操作的对象,第二个参数为 true 表示直接将查询字符串转为一个对象(通过 query 属性来访问)var parseObj = url.parse(req.url, true) var comment = parseObj.query 数组.push(comment)
-
单独获取不包含查询字符串的路径部分(该路径不包含 ? 之后的内容)(
pathname
方法)var pathname = parseObj.pathname
-
如何设置一个共享目录,(如果请求路径是以 /public/ 开头的,则认为要获取 public 中的某个资源)
if (pathname.indexOf('/public/') === 0) { fs.readFile('.' + pathname, function (err, data) { if (err) { res.end('404') } res.end(data) }) }
-
请求路径当作文件路径来直接进行读取
fs.readFile('.' + pathname, function (err, data) { if (err) { return res.end('404 Not Found.') } res.end(data) })
-
如何通过服务器让客户端重定向?
// 1. 状态码设置为 302 临时重定向(不会记住,还会向服务器请求一个) 301是永久重定向(计算机会记住)
// statusCode
// 2. 在响应头中通过 Location 告诉客户端往哪儿重定向
// setHeader
// 如果客户端发现收到服务器的响应的状态码是 302 就会自动去响应头中找 Location ,然后对该地址发起新的请求
// 所以就能看到客户端自动跳转了
res.statusCode = 302
res.setHeader('Location', '/')
res.end()
5.Node中的模块系统
exports 与 require
使用exports时
导出多个成员:exports.xxx=xxx
也可以:module.exports = {}
导出单个成员:module.exports
require加载规则
-
核心模块与第三方模块 —模块名
-
用户写的 ----路径方式
-
优先从缓存加载
若一个模块被加载过,就直接出结果,不会再去重新加载
-
核心模块
-
路径形式的文件模块
-
第三方模块
-
node_modules/
-
package.json
-
上一级上一级的寻找
-
npm(node pavkage manage)
使用的网站 npmjs.com 可以查包
常用命令
- 创建一个项目 `npm init` 【-y】不需要一直回车
- 下载 `npm install 包名`
- 删除 `npm uninstall 包名` 加上 --save可以将顺带着的依赖删除
- 查看帮助 `npm --help`
package.json
每个项目根目录下都有一个package.json文件, 直接npm -install 可以直接把所有依赖下载下来
解决被墙问题
npm install --global cnpm
Express的使用
npm install express
是一个开发框架
简单的设置一个服务器
const { static } = require('express')
var express = require('express')
//创建服务器应用程序 creatServer
var app = express()
//公开目录
app.use('/public/',express.static('./public/'))
//当服务器收到get请求 / 时,执行回调函数
app.get('/',function(req, res){
res.send('hello word')
})
app.get('/about',function(req, res){
res.send('关于我')
})
//req.query 直接以对象形式获取get方法后面的参数
//相当于server.listen
app.listen(3000,function(){
console.log('running....')
})
修改完代码自动重启
使用第三方命名行工具 nodemon
npm install --global nodemon
安装完成后
nodemon app.js
通过nodemon
启动的服务,会监视文件变化并自动重启
在express中配置使用art-template模板引擎
安装
npm install --save art-template
npm install --save express-art-template
配置
//配置使用art-template 模板引擎
app.engine('html', require('express-art-template'));
使用
app.get('/',function(req, res){
//express 默认去项目中的 views 目录找index.html
res.render('index.html',{
title: 'hello'
})
res.send('hello')
})
如何解决获取post请求内容,需要第三方包:body-parser
安装
npm install --save body-parser
配置
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse application/x-www-form-urlencoded
//可以通过req.body来获取表单POST请求数据
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.body, null, 2))
})
path模块
6.CRUD
路由设计
请求方法 | 请求路径 | get 参数 | post 参数 | 备注 |
---|---|---|---|---|
GET | /studens | 渲染首页 | ||
GET | /students/new | 渲染添加学生页面 | ||
POST | /studens/new | name、age、gender、hobbies | 处理添加学生请求 | |
GET | /students/edit | id | 渲染编辑页面 | |
POST | /studens/edit | id、name、age、gender、hobbies | 处理编辑请求 | |
GET | /students/delete | id | 处理删除请求 |
提取路由模块
var router = require('./router')
//把路由容器挂载到app服务中
app.use(router)
router.js
var fs =require('fs')
var Student = require('./student')
var express = require('express')
//1.创建一个路由容器
var router = express.Router()
//2.把路由挂载到 Router 路由容器中
//渲染首页
router.get('/students', function (req, res) {
Student.find(function (err, students) {
if (err) {
return res.status(500).send('Server error.')
}
res.render('index.html', {
fruits: [
'苹果',
'香蕉',
'橘子'
],
students: students
})
})
})
//渲染添加学生页面
router.get('/students/new', function (req, res) {
res.render('new.html')
})
//处理添加学生请求
router.post('/students/new', function (req, res) {
//1.获取 数据
// console.log(req.body)
//2.处理
//将数据保存到db.json文件中用以持久化
//3.发送响应
Student.save(req.body,function (err) {
if (err) {
return res.status(500).send('Server error.')
}
res.redirect('/students')
})
})
//渲染编辑页面
router.get('/students/edit', function (req, res) {
// res.render('edit.html',{
// student:
// })
Student.findById(parseInt(req.query.id), function(err, student){
if (err){
return res.status(500).send('Server error.')
}
res.render('edit.html', {
student: student
})
})
})
//处理编辑请求
router.post('/students/edit', function (req, res) {
Student.updateById(req.body, function(err){
return res.status(500).send('Server error.')
})
res.redirect('/')
})
//处理删除请求
router.get('/students/delete', function (req, res) {
Student.deleteById(req.query.id, function(err){
if (err){
return res.status(500).send('Server error.')
}
res.redirect('/students')
})
})
//3.导出router
module.exports = router
自己编写时的步骤
- 处理模板
- 配置开放静态资源
- 配置模板引擎
- 简单路由: /students渲染静态页出来
- 路由设计
- 提取路由模块
- 封装业务操作 student.js
- 实现具体功能
get,post处理数据
get:req.qurey
post:req.body
7.回调函数!!!
就是为了取函数内部异步操作的结果!
setTimeout
aiax
readFile
writeFile
等等
function add(x,y,callback){//callback可以随便起名字,用一个函数来当作参数
console.log(1)
setTimeout(function(){
var ret = x+y
callback(ret)
},1000)
}
//使用函数的时候再去关心这个callback
add(10,20,function(ret){
console.log(ret)
})
8.MongoDB
是非关系型数据库 就是key-value
对
启动
手动创建/data/db文件夹
mongod 输入后启动成功
停止
Ctrl + C
连接
mongo
退出
exit
基本命令
-
show dbs
查看数据库 -
db
查看当前操作的数据库 -
use 数据库名称
切换到指定数据库(没有的话会新建) -
db.xxx.insertOne({"name": Jack})
插入数据 -
show collections
查看表 -
db.xxx.find()
查找所有数据 -
db.student.inserOne({“name”: “张三”,
“gender”: 0,
“age”: “18”,
“hobbies”: “吃饭、睡觉”})
基本概念
- 数据库
- 集合
- 文档、
在Node中操作MongoDB、
使用mongoose
来操作
https://mongoosejs.com/
7.Promise
promise语法
var fs = require('fs')
//创建 Promise 容器
//这里的resolve 和 reject本身又是个函数
var p1 = new Promise(function(resolve, reject){
fs.readFile('./data/a.txt', 'utf8', function(err, data){
if (err){
//失败 就将容器的pending状态变为Rejected
reject(err)
}else{
//成功 就将容器的pending状态变为Resolved
resolve(data)
}
})
})
//当p1成功了 然后(then)做指定操作
p1.
then(function(data){
console.log(data)
}, function(err){
console.log(err)
})
解决顺序问题
var fs = require('fs')
//创建 Promise 容器
var p1 = new Promise(function(resolve, reject){
fs.readFile('./data/a.txt', 'utf8', function(err, data){
if (err){
//失败 就将容器的pending状态变为Rejected
reject(err)
}else{
//成功 就将容器的pending状态变为Resolved
resolve(data)
}
})
})
var p2 = new Promise(function(resolve, reject){
fs.readFile('./data/b.txt', 'utf8', function(err, data){
if (err){
//失败 就将容器的pending状态变为Rejected
reject(err)
}else{
//成功 就将容器的pending状态变为Resolved
resolve(data)
}
})
})
var p3 = new Promise(function(resolve, reject){
fs.readFile('./data/c.txt', 'utf8', function(err, data){
if (err){
//失败 就将容器的pending状态变为Rejected
reject(err)
}else{
//成功 就将容器的pending状态变为Resolved
resolve(data)
}
})
})
//当p1成功了 然后(then)做指定操作
p1.
then(function(data){//这里这个function就是前面的resolve
console.log(data)
/**
* 当p1读取成功的时候 当前函数中return的结果就可以在 then 中function 接收到
* 当return一个 Promise对象时 后续的 then 方法的第一个参数会作为p2的
*/
return p2
}, function(err){//这里的function是前面的reject
console.log(err)
}).then(function(data){//这个function是p2的resolve
console.log(data)
return p3
}).then(function(data){//这个function是p3的resolve
console.log(data)
})
封装 promise 的例子
var fs = require('fs')
function pReadFile(filePath){
return new Promise(function(resolve, reject){
fs.readFile(filePath, 'utf8', function(err, data){
if (err){
//失败 就将容器的pending状态变为Rejected
reject(err)
}else{
//成功 就将容器的pending状态变为Resolved
resolve(data)
}
})
})
}
pReadFile('./data/a.txt')
.then(function(data){
console.log(data)
return pReadFile('./data/b.txt')
}).then(function(data){
console.log(data)
return pReadFile('./data/c.txt')
}).then(function(data){
console.log(data)
})