2021-12-30,23:23,很冷,有点困,但是据刚回到寝室的一位室友所说,寝室竟然只有他一人——太卷了,太卷了,我真的好爱他们啊!
哦对了,本篇博文还有一篇前置博文哦(Node.JS基础),零基础的朋友可以先通过简单阅读那篇文章快速上手哦
2021/12/30
开始写吧,希望接下来的学习能够顺利!
2021/12/31
说好一起通宵写代码,结果好家伙拉着我打金铲铲之战打到凌晨五点就为了进一次前四…
2021/1/1
争取今天能够写完吧
2021/1/2
本来还想写实际开发过程中遇到的一些问题,不过3号的下午六点作业提交就要截止了,接口那些都还没开始动,可能就没时间写这部分了,以后有机会再补上
众所周知,计算机执行代码之前,会先把高级语言/汇编语言编译成机器代码,
但是JS啊,能被我们浏览器的引擎(说的就是你,ChromeV8)编译,但是却不能直接被计算机编译,
这个脚本,就是逊啦!
但是现在好啦,Node出现了,它是一个V8的容器,只需要装上Node,我们就能利用这个V8引擎脱离浏览器运行我们的脚本语言——哦不,此时已经飞升成面向对象语言的JS!
Node究竟是何方神圣能够把JS带出浏览器的小圈子呢?
因为它底层是C++写的,本身就能在浏览器外跑…
要学计网了,这块也得学着走了
什么?你问我为什么这学期计网都结课了还说这话?
我能咋整嘛,太菜了跟不上,还不是只能自己下来补呜呜呜~
也没啥好说的,这小节不重要(但是还是写下来了,问就是强迫症)
主要分为三步:
1.发送请求
DNS解析,建立TCP连接,发起HTTP请求
(TCP啊,以后学计网再写一篇细说这些)
2.处理请求
服务端接收HTTP请求,进行处理
3.响应数据
服务端发送数据给客户端,客户端接收数据
const http = require('http')
// 创建服务器对象,处理 请求 和 响应
const server = http.createServer((req, res) => {
// 响应
res.end('Hello Server')
})
// 监听2333端口,成功监听则执行回调函数
server.listen(2333,() => {
console.log('服务器已在2333端口开启!')
})
其实至今我都背不下GET和POST的区别,这次再学下
其实上一节中的代码就处理了一个GET请求
我们现在来试着处理一下GET请求
先看一下URL,大概长这样
http://localhost:2333/?name=syy&&password=123456/
我们可以如下书写代码,来基本地处理请求
const http = require('http')
const qs = require('querystring')
// 服务端,处理 请求 和 响应
const server = http.createServer((req, res) => {
// 处理GET
console.log('这是method', req.method)
console.log('这是url', req.url)
console.log('这是首个参数', qs.parse(req.url.split('/?')[0]))
res.end('Hello Server')
})
server.listen(2333,() => {
console.log('服务器已在2333端口开启!')
})
哦,需要注意,这里的querystrig包已经被弃用了,但是问题不大,
我们只需要ctrl + 鼠标左键点击方法名称,就可以观察其源码
可以看到这里有个注解
这里我们只需要删掉这一行就可以继续用了
(当然,也可以自己在通过cv大法把这段代码封装,避免以后真的被删除了没方法可以用了)
进行URL带参数的GET请求,可以在终端看到如下结果
至于第二个GET请求,也就是这个favicon.ico,它是网页标题前的一个小图标,比如下面这样
再说POST请求之间,先写一个index.html作为前端页面,然后手写一个简单的AJAX请求
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<button onclick="AJAX(1)">发送POST请求button>
<button onclick="AJAX(2)">发送GET请求button>
body>
<script>
function AJAX(model){
let xhr = new XMLHttpRequest()
xhr.withCredentials=true
if(!xhr){
console.log('XMLHttpRequest对象创建失败')
return
}
if(model == 1)
xhr.open('POST','http://localhost:2333/index.html')
else if(model == 2)
xhr.open('GET', 'http://localhost:2333/index.html')
xhr.send()
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
let data = JSON.parse(xhr.responseText)
console.log('这是响应的数据', data)
} else {
console.warn('没有正确地响应!')
}
}
}
}
script>
html>
原生Node解决跨域
之后,我们还需要注意,这里由于端口号不同,所以会有跨域问题出现
这里就要给广大的前端学习者们说明一下,跨域就该由后端来解决,所以很多时候,当后端甩锅给前端让前端配置反向代理什么之类的都是后端懒!
后端大概写成这样
const http = require('http')
// 服务端,处理 请求 和 响应
const server = http.createServer((req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5500')
res.setHeader("Access-Control-Allow-Methods", "PUT,POST,DELETE")
res.setHeader("Access-Control-Allow-Headers", "Content-Type,token")
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Content-Type', 'application/json;charset=utf-8;');
res.end(JSON.stringfy({
msg:'成功辣兄弟们!!!'
}))
})
server.listen(2333,() => {
console.log('服务器已在2333端口开启!')
})
对了,还要很多简单的小框架可以使用,这样用起来更方便
安装express模块:
npm install express --save
别和我说你看到这里的时候还不会用npm
之前简单了解了两种请求,现在来写一写:
首先我们先小小地调整一下AJAX
function AJAX(model){
let xhr = new XMLHttpRequest()
xhr.withCredentials=true
if(!xhr){
console.log('XMLHttpRequest对象创建失败')
return
}
if(model == 1) {
xhr.open('POST','http://localhost:2333/index.html?user=碳苯&age=19')
xhr.send({time: new Date()})
}
else if(model == 2){
xhr.open('GET', 'http://localhost:2333/index.html')
xhr.send()
}
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
let data = JSON.parse(xhr.responseText)
console.log('这是响应的数据', data)
} else {
console.warn('没有正确地响应!')
}
}
}
}
服务端也相应地来一点小小的改动
const server = http.createServer((req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5500')
res.setHeader("Access-Control-Allow-Methods", "PUT,POST,DELETE")
res.setHeader("Access-Control-Allow-Headers", "Content-Type,token")
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Content-Type', 'application/json;charset=utf-8;');
const method = req.method
const url = req.url
const path = url.split('?')[0]
const query = qs.parse(url.split('?')[1])
const resData = {
method,
url,
path,
query
}
if(req.method == 'GET') {
res.end(JSON.stringify({
msg:'GET成功辣兄弟们!!!'
}))
} else if(req.method == 'POST') {
let postData = ''
req.on('data', chunk => {
postData += chunk.toString()
})
req.on('end', () => {
resData.postData = postData
res.end(
JSON.stringify(resData)
)
})
}
})
通过阅读以上代码,我们可以看到,我们通过数据流的形式来处理POST请求
虽然有一点中文乱码,不过问题不大,应该设置一下请求头就好了
另外postData没有展开,这个问题不大,实在不行利用深拷贝重新写一个对象传回去
在学会请求之后,咱们也得准备正式开发了
为了熟悉每一个文件和相关配置的具体作用,我们就不新建项目了直接在这几个文件的基础上进行改动吧
其实就是懒
这里大概是遵循了什么三层架构什么的,但是由于我没有过相关知识的学习经历,所以对这一块的内容还是感到生疏,做的笔记也只能说是照猫画虎有样学样,还不能系统地总结。
1.创建www.js
我们建一个文件叫做www.js,先写个板子
const http = require('http')
const server = http.createServer((req, res) => {
res.end('WWW.JS')
})
server.listen(6666, () => {
console.log('server running at port 6666')
})
为了方便维护,我们把createServer里面的回调提出来单独写一个文件叫做app.js
2.创建app.js
先写个基础的板子
const serverHandler = (req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
res.setHeader("Access-Control-Allow-Methods", "PUT,POST,DELETE")
res.setHeader("Access-Control-Allow-Headers", "Content-Type,token")
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Content-Type', 'application/json;charset=utf-8;');
const resData = {
name: 'SYY',
nickName: '碳苯Carbon',
id: 1024
}
res.end(
JSON.stringify(resData)
)
}
module.exports = serverHandler
记得exports导出之后,还要回到www.js里面require引入一下
const app = require('./app.js')
3.设置入口文件
在package.json中修改一下这一行
修改成www.js
开发依赖和依赖的区别就是顾名思义
开发依赖在普通用户使用的时候实际上是不需要的,但是在开发的过程中可能会有比较重要的作用,比如辅助调试之类的
这里要安装的nodemon就是一个做热重载的开发依赖nodemon
# 注意这里要一定写大写D
npm i nodemon -D
然后我们到package.json中康康
之后我们顺便在package.json添加一个命令dev
之后我们就可以用npm run dev来执行nodemon ./www.js了,
这样就可以有一个具有热重载的后端了
npm run dev
淦,这里我的6666端口被占用了,网页打不开,所以只好换了个端口4567
(记得把所有该端口响应地修改一下)
修改的时候就体现出全局变量的好处了啊
利用刚才的index.html(记得修改AJAX中的URL)
就很棒
由于是原生,所以定义接口的方式很原始,真的很原始啊
1.创建一个文件夹放各个路由
const handelTestRoute = (req, res) => {
const method = req.method
const url = req.url
const path = url.split('?')[0]
console.log(path)
if(method == 'GET' && path == '/test_route') {
return {
msg: '这是测试用的接口'
}
} else {
return {
msg: '阿巴阿巴'
}
}
}
这里我们有返回值,所以还需要在某个地方接收这个返回值,而这个地方正是我们的app.js
输入URL测试一下
3.加大难度
首先改一下app.js
}
const testRouteData = handleTestRoute(req, res)
if(testRouteData) {
res.end(
JSON.stringify(testRouteData)
)
} else {
res.writeHead(404,{'Content-Type':'text/plain'})
res.write('404 Not Found!!!!')
res.end()
}
然后是路由本身再改改
const handleTestRoute = (req, res) => {
const method = req.method
const url = req.url
const path = url.split('?')[0]
console.log(path)
if(method == 'GET' && path == '/test_route') {
return {
msg: '这是测试用的接口'
}
}
}
module.exports = handleTestRoute
还有ajax的url
(略)
404——这就对了!
终于,自从ES6有了class之后,现在才是第一次用
1.新建文件夹和文件
新建这个文件主要是为了统一各种数据的格式,以达到一种规范化的效果
2.书写如下代码
// 基类
class BaseModel {
constructor(data, msg) {
// 理想的参数类型是对象,但是如果传进来的是字符串也需要处理一下
if(typeof data == 'string') {
this.msg = data
// null,接下来就可以视为对象
data = null
// 同上
msg = null
}
if(data) {
this.data = data
}
if(msg) {
this.msg = msg
}
}
}
// 成功模型
class SuccessModel extends BaseModel {
constructor(data, msg) {
super(data, msg)
this.err = 0
}
}
// 失败模型
class ErrorModel extends BaseModel {
constructor(data, msg) {
super(data, msg)
this.err = -1
}
}
module.exports = {
SuccessModel,
ErrorModel
}
注意,其中基类的代码,
因为理想的参数是对象,但是如果强行传进一个字符串作为参数,那么就需要特殊处理一下方便后续流程的进行
这里所谓的后续流程,看似只有后面两个if,感觉改为else就足够了,但考虑到后续的维护,我们还是有必要做这种处理
这种处理在开发中很常见
把字符串信息保存进this.msg,然后把msg和data置为null,这样就能够看做一个为空的对象了
相关方法
1.创建Controller文件夹和文件
因为书写过程中会使用到一些自定义的方法,为了方便维护我们把它们放到一起
即这里创建的controllers文件夹
2.书写如下代码
const getData = () => {
return [
{
id: 1,
name: '香甜的甲基橙',
appearance: '(owo)',
motto: '爱自己,更要爱别人'
},
{
id: 2,
name: '碳苯',
appearance: '(nvn)',
motto: '胸怀明月,目蕴骄阳'
}
]
}
module.exports = {
getData
}
由于改动太大了,比如上面改个端口都要到各个文件里面相应地改一下,或者说写完方法之后在某个文件中添加调用的语句…这样的一些改动我就不演示了,不然篇幅实在是太过于冗余,还望海涵
本来是想用MySQL,结果期末作业要求SQLServer我人麻了> 整了一晚上根本不晓得怎么连接
算了放弃吧,还是用MySQL糊弄过去得了
这里用的是mysql,代码如下
// const { connect } = require('mssql')
// 垃圾mssql给爷爬,还得是我mysql啊
const mysql = require('mysql')
// 连接
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
port: 3306,
database: 'syyselectcourse'
})
connection.connect()
// 执行sql
const sql = `select * from syystudent`
connection.query(sql, (err, result) => {
if(err) {
console.log(err)
return
}
console.log('result', result)
})
// 关闭连接
connection.end()
运行结果
这里为了演示,就把执行sql和关闭连接写到一个文件里面了,后面记得要拆出来单独写
这里先改成这样:
// const { connect } = require('mssql')
const mysql = require('mysql')
// 连接
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
port: 3306,
database: 'syyselectcourse'
})
connection.connect()
// 执行sql
// const sql = `select * from syystudent`
// connection.query(sql, (err, result) => {
// if(err) {
// console.log(err)
// return
// }
// console.log('result', result)
// })
// function executeSQL(sql, callback) {
// connection(query, callback)
// }
// 还可以进一步优化,用promise来做这个
function executeSQL(sql) {
const promise = new Promise((resolve, reject) => {
connection.query(sql, (err, res) => {
if(err) {
reject(err)
return
}
resolve(res)
})
})
return promise
}
// 关闭连接
// connection.end()
module.exports = {
executeSQL
}
之后如果要执行SQL语句,我们放到路由这里做
比如这样
if (path === '/student') {
const sql = `SELECT * FROM syystudent`
executeSQL(sql).then(res => {
console.log('~~~~~SQL执行成功~~~~~')
console.log(res)
})
}
发一下ajax请求,果然如我所料,稳得一批
那么
大概,就这样了?
当然不是,时间是有限的,但是知识可是无限的!
Node.JS的学习只是告一段落了,但是我并不会停下学习的脚步,在完成作业项目的开发之后,我会把相关内容上传到我的Gitee仓库,并且把更多更详细的内容放到我的个人博客。
我的仓库
Serio的Gitee仓库希望能得到更多星星哦!
我的博客
Serio的个人博客!访问获得更多学习资料!
之后,咱先去复习计网了,再过几天又是要考试考试考试了哈哈哈~~
2022新的一年,大家继续加油啊!