笔记

2020/4/30: Node.js
服务器启动:Error: listen EADDRINUSE: address already in use :::3000
解决方法:找到占用端口程序
netstat -o -n -a | findstr :3000
杀掉该程序:
taskkill /F /PID 11632

POST请求方式:
参数被放置在请求体中进行传输
获取POST参数需要使用data事件和end事件
使用querystring系统模块将参数转换为对象格式

路由:
//1.引入系统模块http
//2.创建网站服务器
//3.为网站服务器对象添加请求事件
//4.实现路由功能
// 1.获取客户端的请求方式
// 2.获取客户端的请求地址

静态资源:
服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如CSS、Javascript、、image文件。
动态资源:
相同的请求地址不同的响应资源,这种资源就是动态资源。
//1.引入系统模块
const http = require('http');
const url = require('url');
const app = http.createServer();
const path = require('path');
const fs = require('fs');
const mime = require('mime');
//2.对服务器对象进行监听,当客户端有请求来的时候
app.on('request', (req, res) => {
//3.获取用户的请求路径
let pathname = url.parse(req.url).pathname;

pathname = pathname == '/' ? 'index.html' : pathname;

//4.将用户的请求路径转换为实际的服务器硬盘路径
let realPath = path.join(__dirname, 'public' + pathname);//路径拼接

let type = mime.getType(realPath);

//5.读取文件
fs.readFile(realPath, (error, result) => {
if (error != null) {
res.writeHead(404, {
'content-type': 'text/html;charset=utf8'
})
res.end('文件读取失败');
return;
}
res.writeHead(200, {
'content-type': type
})
//6.响应给客户端
res.end(result);
});
});
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');

同步API,异步API
同步API:只有当前API执行完成后,才能继续执行下一个API,一行一行执行
console.log('before');

console.log('after');
同步API可以从返回值中拿到API执行的结果,但是异步API是不可以的,可以用回调函数
异步API:当前API的执行不会阻塞后续代码的执行
执行顺序:先执行同步API,把异步api放入异步工作区,再看回调函数
console.log('before');

setTimeout(function() {
console.log('last');
}, 2000)

console.log('after');
回调函数:自己定义函数让别人去调用
function getData(callback){//callback形参
callback('123')
}
getData((n)=>{
console.log('callback函数被调用了')
console.log(n)
});

Promise:
Promise出现的目的是解决Node.js异步编程中的回调地狱的问题。
//在异步函数内部使用return关键字进行结果返回 结果会被包裹在promise对象中,return关键字代替了resolve方法
//调用异步函数再链式调用then方法获取异步函数执行结果
function p1() {
return new Promise((resolve, reject) => {
fs.readFile('./1.txt', 'utf8', (err, result) => {
resolve(result);
});
});
}

function p2() {
return new Promise((resolve, reject) => {
fs.readFile('./2.txt', 'utf8', (err, result) => {
resolve(result);
});
});
}

function p3() {
return new Promise((resolve, reject) => {
fs.readFile('./3.txt', 'utf8', (err, result) => {
resolve(result);
});
});
}

p1().then((r1) => {
console.log(r1);
return p2();
})
.then((r2) => {
console.log(r2);
return p3();
})
.then((r3) => {
console.log(r3);
})

5.9异步函数
异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了
//1.在普通函数定义的前面加上async关键字 普通函数就变成了异步函数
//2.异步函数默认的返回值是promise对象
//3.在异步函数内部使用throw关键字进行错误的抛出
//调用异步函数再链式调用catch方法获取异步函数执行的错误信息

async function fn() {
throw '发生了一些错误';
return 123;
}
// console.log(fn());
fn().then(function(data) {
console.log(data);
}).catch(function(err) {
console.log(err);
})
//await关键字
//1.它只能出现在异步函数中
//2.await promise 它可以暂停异步函数的执行 等待promise对象返回结果后再向下执行函数

async function p1() {
return 'p1';
}
async function p2() {
return 'p2';
}
async function p3() {
return 'p3';
}
//顺序输出
async function run() {
let r1 = await p1()
let r2 = await p2()
let r3 = await p3()
console.log(r1);
console.log(r2);
console.log(r3);
}
run();

MongoDB数据库连接:
net start MongoDB
//引入mongoose第三方模块 用来操作数据库
const mongoose = require('mongoose');
//数据库连接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true, useUnifiedTopology: true })
//连接成功
.then(() => console.log('数据库连接成功'))
//连接失败
.catch((err => console.log(err, '数据库连接失败')))连接失败')))

3.1创建集合
创建集合分为两步,一是对集合设定规则,二是创建集合,创建mongoose.Schema构造函数的实例即可创建集合。
const courseSchema = new mongoose.Schema({
name: String,
author: String,
isPublished: Boolean
});
const Course = mongoose.model('Course', courseSchema) //courses
3.2创建文档
创建文档实际上就是向集合中插入数据。
分为两步:
1.创建集合实例。
2.调用实例对象下的save方法将数据保存到数据库中。
//1.创建集合实例
const course = new Course({
name: 'node.js基础',
author: '黑马讲师',
isPublished: true
})

// 2.调用实例对象下的save方法将数据保存到数据库中。
course.save();
或者:
Course.create({ name: 'Javascript', author: '黑马讲师', isPublished: false }, (err, result) => {
console.log(err);
console.log(result);

})
查询
//查询用户集合中的所有文档
// User.find().then(result => console.log(result));
//通过_id字段查找文档
// User.find({ _id: '5e b1160e8f14ec1d39eb9d95 ' }).then(result => console.log(result));
//findOne方法返回一条文档
// User.findOne().then(result => console.log(result))
// User.findOne({ username: '李白' }).then(result => console.log(result)) user
//根据条件查询
//匹配 大于 小于
User.find({ age: { $gt: 20, $lt: 40 } }).then(result => console.log(result))
//匹配包含
User.find({ age: { $gt: 20, $lt: 40 } }).then(result => console.log(result))
//选择要查询的字段
User.find().select('name email').then(result => console.log(result))
//将数据按照年龄进行升序排列 降序-age
User.find().sort('age').then(result => console.log(result))
//skip跳过多少条数据 limit限制查询数量
User.find().skip(2).limit(2).then(result => console.log(result))

删除
//删除单个 删除多个deleteMany({})
User.findOneAndDelete({ _age: 22 }).then(result => console.log(result))

更新(改)
//更新单个
User.updateOne({ name: '里斯' }, { name: 'lisi' }).then(result => console.log(result))
//更新多个
User.updateMany({}, { age: 56 }).then(result => console.log(result))

3.6 mongoose验证
const postSchema = new mongoose.Schema({
title: {
type: String,
//必选字段
required: [true, '请传入文章标题'], //自定义报错信息
minlength: [2, '文章长度不能小于2'], //最小长度
maxlength: [5, '文章长度不能大于5'],
trim: true //去除字符串两头空格
},
age: {
type: Number,
min: 18, //数值最小
max: 100 //数值最大
},
publishDate: {
type: Date,
default: Date.now //默认当前时间
},
category: {
type: String,
//枚举 列举出当前字段可以拥有的值
enum: {
values: ['html', 'css', 'javascript', 'node.js'],
message: '分类名称要在一定范围内才可以'
}
},
author: {
type: String,
//自定义验证器
validate: {
validator: v => {
//返回布尔值
//true 验证成功
//false 验证失败
//v 要验证的值
return v && v.length > 4
},
//自定义错误信息
message: '传入的值不符合验证规则'
}
}
});

const Post = mongoose.model('Post', postSchema);

Post.create({ title: ' aa ', age: 20, category: 'html', author: 'bd' })
.then(result => console.log(result))
.catch(error => {
//获取错误信息对象
const err = error.errors;
//循环 错误信息对象
for (var attr in err) {
//将错误信息打印到控制台中
console.log(err[attr]['message']);
}
})

3.7 集合关联
通常不同集合的数据之间是有关系的,例如文章信息和用户信息存储在不同集合中,但是文章是某个用户发表的,要查询文章的所有信息包括发表用户,就需要用到集合关联。
//用户集合
// const User = mongoose.model('User', new mongoose.Schema({ name: { type: String } }));
//文章集合
// const Post = mongoose.model('Post', new mongoose.Schema({title: { type: String },
//使用ID将文章集合和作者集合进行关联
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
}))

3.8案例:用户信息增删改查
1.搭建网站服务器,实现客户端与服务器端的通信
2.连接数据库,创建用户集合,向集合中插入文档
mongoimport -d playground -c users --file ./user.json
尝试mongoimport 导入json文件报错
使用如下命令导入json文件
mongoimport -d playground -c users -file ./user.json
报错如下:
Failed: cannot decode array into a D
当json是一个数组的时候,导入报错,使用参数可以改成以下

mongoimport -d playground -c users --jsonArray ./user.json
3.当用户访问/list时,将所有用户信息查询出来
4.将用户信息和表格Html进行拼接并将拼接结果响应回客户端
5.当用户访问/add时,呈现表单页面,并实现添加用户信息功能
6.当用户访问/modify时,呈现修改页面,并实现修改用户信息功能
7.当用户访问/delete时,实现用户删除功能

1.1模板引擎
模板引擎是第三方模块
让开发者更加友好的方式拼接字符串,使项目代码更加清晰,更加易于维护

1.2 art——template模板引擎
2.6 子模版
使用子模版可以将网站公共区快(头部,底部)抽离到单独的文件中。
标准语法: {{include '模板'}}
原始语法: <% include ('模板')%>

2.7模板继承
使用模板继承可以将网站HTML骨架抽离到单独的文件中,其他页面模板可以继承骨架文件
{{extend './layout.art'}}

2.9模板配置
//导入模板变量
template.defaults.imports.dateFormat = dateFormat;
//设置模板的根目录
template.defaults.root = path.join(__dirname, 'views');
//配置模板的默认后缀
template.defaults.extname = '.html';

3.案例-学生档案管理
目标:模板引擎应用,强化node.js项目制作流程。
知识点:http请求响应、数据库、模板引擎、静态资源访问。
制作流程:
1.建立项目文件夹并生成项目描述文件
2.创建网站服务器实现客户端和服务器端通信
3.连接数据库并根据需求设计学员信息表
4.创建路由并实现页面模板呈递
5.实现静态资源访问
6.实现学生信息添加功能
7.实现学生信息展示功能

3.3 第三方模块 router
功能:实现路由
使用步骤:
1.获取路由对象
2.调用路由对象提供的方法创建路由
3.启动路由,使路由生效

3.4 第三方模块 serve-static
功能:实现静态资源访问服务
步骤:
1.引入serve-static模块获取创建静态资源服务功能的方法
2.调用方法创建静态资源服务并指定静态资源服务目录
3.启用静态资源访问服务功能

posted @ 2020-05-16 18:47  Oreobb  阅读(88)  评论(0)    收藏  举报