赞
踩
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>Document</title> </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端口开启!') })
这里我们采用的是CORS解决跨域
对了,还要很多简单的小框架可以使用,这样用起来更方便
安装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.创建一个文件夹放各个路由
2.创建一个路由
先来随便写一个试试手
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新的一年,大家继续加油啊!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。