@nodejs全栈开发课程笔记
知识点目录
✪ nodejs第一个程序
编写一段js来读取CPU,内存的脚本
demo.js
读取cpu代码片`.
// 读取系统的CPU信息
const os = require('os');
const cups = os.cups(); //获取当前系统的cpu的数量
console.log(cups.length);
//获取内存的信息
const total = os.totalmen(); //bytes
console.log(total/1024/1024/1024); //GB
const free = os.freemen();
console.log(free/1024/1024/1024) //GB
Web服务常用代码片段
// web服务
// ajax-->api-->web server(nodejs)
const http = require('http');
const server = http.createServer((req,res)=>{
res.end('helle')
})
//服务器监听,端口3000,监听本地127.0.0.1
server.listen(3000,'127.0.0.1',()=>{
console.log('服务启动成功')
})
在命令运行
$ node src/demo.js
✪ Nodejs和npm介绍
✪ nodemon介绍
配置nodemon
1、npm i nodemon -D
2、修改 package.json 中的启动命令
"scripts":{
"start":"nodemon src/app.js",
"start:node":"node src/app.js"
}
3、通过增加 nodemon.js 配置文件 指定特殊 watch 的文件
根目录添加 nodemon.json
{
"watch":["./src/**/*.js"]
}
4、通过添加 DEBUG=* 查看运行细节
"scripts":{
"start":"DEBUG=* nodemon src/app.js"
}
✪ 使用nrm和nvm介绍
1、配置nrm
npm i nrm -g
2、常用命令
nrm ls //查看内置元
nrm -h //操作帮助
nrm current //查看当前源
nrm use
有些公司可以自己做自己的源,由内部人员调用使用。
3、使用nvm 管理nodejs 版本
nvm ls-remote --lts //查看远程nodejs的版本列表
nvm i v10.14.1 //安装需要的版本
nvm use v8.9.0 //制定使用当前使用的版本
nvm ls //查看本机现在有的版本
nvm alias default v8.9.0 //默认使用的版本
WEB应用基础
web应用
前端
ajax,ws,—>服务器(web应用) —>缓存/数据库
express
接受 req,处理 res
express·:node 中的一种应用框架
1、配置方法
npm i express -S
2、基础实例
app.js
const express = require('express');
// 是一个express实例
const app = express();
app.use((req,res)=>{
res.json({
name:"詹胜男"
})
})
app.listen(3000,()=>{
console.log("server 启动成功")
})
3、使用get,post的接口方式查看
const express = require('express');
// 是一个express实例
const app = express();
app.get('/name',(req,res)=>{
res.send('tom')
})
app.post('/name',(req,res)=>{
res.send('tom post')
})
app.listen(3000,()=>{
console.log("server 启动成功")
})
4、使用get,post 结合url参数的形式
const express = require('express');
// 是一个express实例
const app = express();
app.get('/name/:age',(req,res)=>{
let {age} = req.params; //接受参数
res.json({
name:"tom",
age
})
})
app.listen(3000,()=>{
console.log("server 启动成功")
})
配图
✪ Route介绍和使用
1、route是什么
web服务 如何处理一个 请求
url → 网络 → dns解析 → 目标服务器
1、如何响应这个请求 → 路由 //规则
- 1、通过 请求的 方法类型 来区分
- 1、get
- 2、post
- 3、put
- 4、delete
- 5、其他
app.get('/demo',(req,res)=>{
})
app.post('/demo',(req,res)=>{
})
- 2、通过 url——路径
eg: www.baidu.com/a/c/a.html- 1、基础知识,通过不同的路由名称
app.get('/user/byname',(req,res)=>{
})
app.get('/user/byid',(req,res)=>{
})
- 2、无论通过什么请求方式,都可以得到响应
app.all('/demo',(req,res)=>{
res.json({
message:'demo',
method:req.method //查看请求的方式
})
})
- 3、无论客户端使用任何的 url,我们的服务都可以响应 (使用场景:日志)
app.all('*',(req,res)=>{
res.json({
message:'demo',
method:req.method, //查看请求的方式
url:req.path //路径
})
})
- 4、app.use — 使用中间件
建议使用场景,中间件注册时候使用。
app.use('/demo',(req,res)=>{
res.json({
message:'demo',
method:req.method //查看请求的方式
})
})
app.use((req,res)=>{
res.json({
message:'demo',
method:req.method, //查看请求的方式
url:req.path //路径
})
})
-
5、如何做路由的拆分
eg.一个多功能的商城,有用户(meber)、商品(sku)、订单(order)
使用 express.Router
方式:
1、在src目录下面新建系列中间件js文件,例如:member.router.js、sku.router.js、order.router.js
member.router.js 代码片段
const express = require('express');
const router = express.Router();
// 便可直接使用需要的路由方法,以下为打比方
router.get('/user/byname',(req,res)=>{...})
router.post('/user/byname',(req,res)=>{...})
router.all('*',(req,res)=>{...})
router.use('/user/byname',(req,res)=>{...})
router.use((req,res)=>{...})
//具体事例
router.get('/list',(req,res)=>{
res.json({
list:[
{
id:001,
name:'李四'
}
]
})
})
module.exports = router; //将路由暴露出去
2、在app.js文件注册路由
...
const app = express();
//注册路由
const memberRouter = require('./member.router');
app.use(memberRouter)
同理,在src文件夹下面,建立 sku.router.js、order.router.js
再在app.js中注册,注意,多个路由中避免重复命名的list,要在注册路由是添加二级路径区分。
app.js代码片段
...
//注册路由
const memberRouter = require('./member.router');
const skuRouter = require('./sku.router');
app.use('/member',memberRouter)
app.use('/sku',skuRouter )
postman访问地址分别为:
http://127.0.0.1/member/list
http://127.0.0.1/sku/list
✪ 中间件介绍与使用
一、中间件完整的结构
1、是一个函数
2、支持的入参有err、req、res、next → 他们可以是function
例如:
function demo_middleware(err,req,res,next){
//功能
// 1、处理异常
// 2、处理下业务功能,然后转交控制权——next
// 3、响应请求——结束请求 ,即为:当做路由的处理函数。或者说,路由是中间件的一种
}
例如,在请求前检查是否有参数传入。
// 校验功能函数
function valid_name_middleware(req,res,next){
let {name} = req.query;
if(!name || name.length){
res.json({
message: "缺少name参数" //不满足要求,提示。
})
}else{
next() //满足不为空,爱怎么着下一步就怎么走
}
}
// 检查所有访问请求是否都满足“校验功能函数”的条件
app.all('*',valid_name_middleware) //顺序执行的拦路虎
// 通过拦路虎,继续往下执行其他函数
...
测试:
不通过 = http://127.0.0.1:3000/test?name=’’
通过 = http://127.0.0.1:3000/test?name=112
二、中间件分类
1、app 级别的使用
1。 注册的时候,一定是最顶的
2。通过app.use,将api加载进来
例如:
....
//加载自定义的中间件
function log_middleware(req,res,next){
console.log('请求来了');
next();
}
app.use(log_middleware);
// 加载系统中已有中间件,例如一个静态页面 express.static 中间件
// 直接写 app.use
app.use(express.static('staticfile',{
}))
// 新建一个 staticfile 文件夹,里面新建一个 index.html 的静态页面
// 浏览器直接输入 http://1278.0.0.1:3000/index.html 就可以访问了
// 注意不能写为 http://1278.0.0.1:3000/index 除非补充一个拓展说明,如下
app.use(express.static('staticfile',{
extensions:['html','htm']
}))
...
// 拓展学习可以有 express.json、express.urlencoded
// 具体可查看 express官网的guid
2、router 级别
1、基础认识
首先在 src 文件夹下,新建 router 文件夹,再在router 文件夹下新建 user_router.js文件
user_router.js代码片段
const express = require('express');
const router = express.Router(); //路由对象
router.get('/demo',(req,res)=>{
res.json({
message:'from router demo'
})
})
module.exports = router;
app.js 引入路由
//注册路由
const userRouter = require('./router/user_router');
app.use('/user',userRouter)
2、路由级别加入“加入执行函数”
路由级别的也可以有处理函数。可在 user_router.js 文件中,加入执行函数,
例如
const express = require('express');
const router = express.Router(); //路由对象
/// 本节知识点新增代码
router.use(function(req,res,next){
console.log('log from router');
next();
})
router.get('/demo',(req,res)=>{
res.json({
message:'from router demo'
})
})
module.exports = router;
3、路由级别,路由内部使用的中间件函数
user_router.js
router.get('/demo',[/** middleware 链式的 **/](req,res)=>{
res.json({
message:'from router demo'
})
})
router.get('/demo',[functionA,functionB...](req,res)=>{
res.json({
message:'from router demo'
})
})
实例,校验路由传递过来的name、password:
http://127.0.0.1:3000/user?name=tom"&password=123"
user_router.js
function vlaid_login_params(req,res,next){
//初始化参数名
let {name,password} = req.query;
if(!name || !password){
res.json({
message:"参数 校验失败"
})
}else{
req.formdata = {
name,
password
}
next();
}
}
router.get('/demo',[vlaid_login_params](req,res)=>{
let {formdata} = req;
res.json({
formdata,
message:'from router demo'
})
})
3、异常处理
也可以是属于app级别、router级别,看划分的曾经和想抛出异常的地方。
一、异常捕获
制造一个异常代码,由express框架将异常将其捕获,往外抛出
app.get('/demo',(req,res)=>{
res.json({
message //异常代码,没有定义参数
})
})
捕获异常
app.get('/demo',(req,res)=>{
//捕获异常
throw new Error('测试异常功能')
res.json({
message //异常代码,没有定义参数
})
})
二、Express 内置异常处理
定义一个异常处理的中间件
function error_handler_middleware(err,req,res,next){
if(err){
res.status(500)
.json({
message:'服务器异常'
})
}else{
next()
}
}
app.use(error_handler_middleware)
针对404的异常处理
在express框架中,404不属于异常,虽然他提示是error,但是没有做处理,因此我们可以专门定义一个针对404的中间件,提示“api不存在”,这个中间件的特点在于,没有 error 参数。
function not_found_handler_middleware(req,res,next){
res.json({
message:'api不存在'
})
}
app.use(not_found_handler_middleware)
三、自定义异常处理
function demo_middleware(req,res,next){
try {
// do something
}catch (error){
//抛出异常说明
}
}
✪ Mysql介绍与安装
安装包在百度云盘
1、mysql – 结构化数据库,中的一种
2、mysql – 服务, 提供了数据存放的服务
|——数据库:划分的存储区域
|——table:
|—— 对象数组
|—— js对象数组
[
{
id:1,
name:‘计算机编程’
},
{
id:2,
name:‘C++’
}
]
✪ Sequelize介绍和使用
1、什么是ORM
对象模型数据库,将数据中的表,用对象的方式输出出来,通过js读取出来
2、Sequelize 作用
安装与初始化
cnpm i sequelize sequelize-cli mysql2 -S
npx sequelize-cli init
为什么要装mysql2,因为以下操作路径:
node-application - ORM(sequlize) --> 驱动(node-mysql) --> mysql db
当提示 npm WARN XXX@XXX no description时,添加"private": true, 即可。
3、在nodejs应用中集成sequelize
新建表
npx sequelize-cli model:generate --name User --attributes name:string
将表加入数据库
npx sequelize-cli db:migrate -env=development
新建可以在前端录入数据的函数
//使用模型对象
const models = require('../models');
app.get('/create',async (req,res)=>{
let {name} = req.query;
// promise user -->sequlize 对象
let user = await models.User.create({
name
})
})
Todo实例模型
初始化数据库
1.创建一个数据库
2.使用sequlize cli
初始化 项目的数据库配置信息
npx sequlize-cli init
先新建一个db文件夹,再做初始化
3.生成模型文件
1.migrate 文件夹
2.model 文件
npx sequelize-cli model:generate --name Todo --attributes name:string,deadline:date,content:string
4.持久化,模型对应的【数据库表】
npx sequelize-cli db:migrate -env=development
注意,去掉不想要自动声明的 createdate,updatedate。
timestamps:false // 不让他自动创建 记录更新时间
'use strict';
module.exports = (sequelize, DataTypes) => {
const Todo = sequelize.define('Todo', {
name: DataTypes.STRING,
deadline: DataTypes.DATE,
content: DataTypes.STRING
}, {
timestamps:false // 不让他自动创建 记录更新时间
});
Todo.associate = function(models) {
// associations can be defined here
};
return Todo;
};
API里面具体使用ORM模型
安装body-parser
cnpm i body-parser -S
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(express.json());
// for parsing application/xwww-form-urlencoded
app.use(express.urlencoded());
// for parsing application/xwww-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true}))
//使用模型对象,因为sequlize安装在了一个db文件夹,所以记得加上../db/
const models = require('../db/models');
// 1.所有的错误,http status =500
/* 查询任务列表 */
app.get('/list/:status/:page',async (req,res,next)=>{
res.json({
list:[]
})
})
/* 创建 一个 todo 测试用
app.post('/create',async (req,res,next)=>{
let {name,deadline,content} = req.body;
res.json({
todo:{},
name,
deadline,
content
})
})
*/
/* 创建 一个 todo 真实使用model对象时*/
app.post('/create',async (req,res,next)=>{
try{
let {name,deadline,content} = req.body;
let todo = await models.Todo.create({
name,
deadline,
content
})
res.json({
todo,
message:"创建成功"
})
}catch (err){
next(err)
}
})
/* 修改 一个 todo 测试用
app.post('/update',async (req,res,next)=>{
let {name,deadline,content,id} = req.body;
res.json({
todo:{},
name,
deadline,
content,
id
})
})
*/
app.post('/update',async (req,res,next)=>{
try{
let {name,deadline,content,id} = req.body;
let todo = await models.Todo.findOne({
where:{
id
}
})
//上一步执行查找以后,接着判断是否找到了todo
if(todo){
// 执行更新功能,因为todo是上面let已经定义的models对象,所以直接使用即可
todo = await todo.update({
name,
deadline,
content
})
}
res.json({
todo
})
}catch (err){
next(err)
}
})
/* 修改 一个 todo, 删除 测试用
app.post('/update_status',async (req,res,next)=>{
let {id,status} = req.body;
res.json({
todo:{},
id,
status
})
})
*/
/* 修改 一个 todo, 删除 */
app.post('/update_status',async (req,res,next)=>{
try{
let {name,deadline,content,id} = req.body;
let todo = await models.Todo.findOne({
where:{
id
}
})
//上一步执行查找以后,接着判断是否找到了todo.,多了一个判断状态是否更新
if(todo && status!=todo.status){
// 执行更新功能,因为todo是上面let已经定义的models对象,所以直接使用即可
todo = await todo.update({
status
})
}
res.json({
todo
})
}catch (err){
next(err)
}
})
app.get('/list/:status/:page',async (req,res,next)=>{
let {status,page} = req.params;
let limit = 10;
let offset = (page-1)*limit;
let where = {}
// 1.状态 1:表示待办,2:完成,3:删除,-1:全部
// 2.分页的处理
if(status != -1){
where.status = status;
}
let list = await models.Todo.findAndCountAll({
where,
offset,
limit
})
res.json({
list,
message:"列表查询成功"
})
})
app.get('/detail/:id',async (req,res)=>{
let {id} = req.params;
let user = await models.User.findOne({
where:{
id
}
})
res.json({
user
})
})
app.use((err,req,res,next)=>{
if(err){
res.status(500).json({
message:err.message
})
}
})
app.listen(3000,()=>{
console.log("server 启动成功")
})