本文最后更新于:2024年11月17日 晚上
1.服务器端基础概念
1.1URL
统一资源定位符,又叫 URL(Uniform Resource Locator),是专门为标识 Internet 网上资源位置而设的一种编址方式,我们平时所说的网页地址指的即是 URL
URL 的组成
传输协议:服务器 ip 或域名:端口资源所在位置标识
http://www.badspider.top/page/1024.html
http:超文本传输协议,提供了一种发布和接受 HTML 页面的方法
关于端口,我们输入网址的时候是不需要写的,因为浏览器在请求的时候会默认加上 80 端口
1.2 开发过程中客户端和服务器端说明
在开发阶段,客户端和服务器端使用同一台电脑,即开发人员电脑
开发人员电脑
客户端(浏览器)
服务器端(Node)
本机域名:localhost
本地 ip:127.0.0.1
2.创建 web 服务器
2.1 创建 web 服务器
1 2 3 4 5 6 7 8 9 10 11 12
| const http = require("http");
const app = http.createSever();
app.on("request", (req, res) => { res.end("<h1>hi,user</h1>"); });
app.listen(3000); console.log("服务器已经启动,监听3000端口,请访问localhost:3000");
|
2.2Http 协议的概念
报文
在 http 请求和响应的过程中传递的数据块就叫报文,包括要传送的数据和一些附加信息,并且要遵守规定好的格式
2.3 请求报文
1.请求方式(Request Method)
GET 请求数据
POST 发送数据 (更安全)
2.请求地址(Request URL)
1 2 3 4 5
| app.on("request", (req, res) => { req.headers; req.url; req.method; });
|
2.4 响应报文
http 状态码
- 200 请求成功
- 404 请求的资源没有被找到
- 500 服务器端错误
- 400 客户端请求有语法错误
内容类型
- text/html
- text/css
- application/javascript
- image/jepg
- application/ json
3.HTTP 请求与响应处理
3.1 请求参数
客户端向服务器端发送请求时,有时需要携带一些客户信息,客户信息需要通过请求参数的形式传递到服务器端,比如登录操作
3.1.1 GET 请求参数
问号后面的就是参数,如果传递多个用&分隔
3.1.2 POST 请求参数
method: 指定当前表单提交的方式
action: 指定当前表单提交的地址
post 参数是通过事件的方式接收的
- data 当请求参数传递的时候触发 data 事件
- end 当参数传递完成的时候触发 end 事件
1 2 3 4 5 6 7 8 9 10 11
| app.on("request", (req, res) => { let postParams = ""; req.on("data", (params) => { postParams += params; }); req.on("end", () => { console.log(postParams); }); res.end("ok"); });
|
3.2 路由
路由是指客户端请求地址与服务器端程序代码的对应关系。简单的说,就是请求什么响应什么
1 2 3 4 5 6 7 8 9 10 11 12
| app.on("request", (req, res) => { let { pathname } = url.parse(req.url); if (pathname == "/" || pathname == "/index") { res.end("welcome to index"); } else if (pathname == "/list") { res.end("welcome to list "); } else { res.end("sorry,404 not found"); } });
|
3.3 静态资源
服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如 CSS,Javascript,image 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| const http = require("http"); const url = require("url"); const path = require("path"); const fs = require("fs");
var app = http.createServer();
app.on("request", (req, res) => { res.writeHead(200, { "content-type": "text/html;charset=utf8", }); let pathname = url.parse(req.url).pathname; let readpath = path.join(__dirname, "public" + pathname); fs.readFile(readpath, (error, result) => { if (error != null) { res.end("文件读取失败"); return; } res.end(result); }); });
app.listen(3000); console.log("It's working");
|
3.4 动态资源
相同的请求地址不同的响应资源,这种资源就是动态资源
4.Node.js 异步编程
4.1 同步 API,异步 API
同步 api:只有当前 api 执行完成后,才能继续执行下一个 api
1 2
| console.log("before"); console.log("after");
|
异步 api:当前 api 的执行不会阻塞后续代码的执行
1 2 3 4 5
| console.log('before') setTimeout( ()=>{console.log('last')} ),2000) console.log('after')
|
4.2 同步 api,异步 api 的区别(获取返回值)
同步 api 可以从返回值中拿到 api 执行的结果,但是异步 api 是不可以的
1 2 3 4 5
| function sum(s1, s2) { return s1 + s2; } const result = sum(10, 20);
|
1 2 3 4 5 6 7 8 9
| function getMsg() { setTimeout(function () { return (msg: "hello node.js"); }, 2000); }
const msg = getMsg(); console.log(msg);
|
4.3 回调函数
自己定义函数让别人去调用
1 2 3 4
| function getData(callback) {}
getData(() => {});
|
4.4 同步 api,异步 api 的区别(代码执行顺序)
同步 api 从上到下依次执行,前面代码会阻塞后面代码的执行
1 2 3 4
| for (var i = 1; i < 1000; i++) { console.log(i); } console.log("it's ending");
|
异步 api 不会等待 api 执行完成后再向下执行代码
1 2 3 4 5 6 7 8
| console.log("代码开始执行"); setTimeout(() => { console.log("ssss"); }, 2000); setTimeout(() => { console.log("aaa"); }, 0); console.log("it's ending");
|
会先执行完同步代码再去回调函数队列中拿回调函数执行
4.5Node.js 中的异步 api
fs.readFile('./demon.text',(err,result)=>{})
回调地狱
1 2 3 4 5 6 7 8 9 10 11
| const fs = require("fs");
fs.readFile("./1.text", "utf8", (err, result1) => { console.log(result1); fs.readFile("./2.text", "utf8", (err, result2) => { console.log(result2); fs.readFile("./3.text", "utf8", (err, result3) => { console.log(result3); }); }); });
|
4.6Promise
Promise 出现的目的是解决 Node.js 异步编程中回调地狱的问题
1 2 3 4 5 6 7 8 9 10 11 12
| let promise = new Promise((resolve,reject)=>{ setTimeout(()=>{ if(true){ resolve({name:'张三'}) } else { reject("失败了") } },2000) }) promise.then(result=>console.log(result)) .catch(error=>console(error))
|
4.7 异步函数
异步函数是异步编程语法的终极解决方案,它可以让外面将异步代码写出同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了
const fn = async()=>{}
async function fn(){}
1.在普通函数定义的前面加上 async 关键字,普通函数就变成了异步函数
2.异步函数默认的返回值是 promise 对象
3.在异步函数内部使用 return 关键字进行结果返回 结果会被包裹的 promise 对象中 return 关键字代替了 resolve 方法
4.在异步函数内部使用 throw 关键字抛出异常
5.调用异步函数再链式调用 then 方法获取异步函数执行结果
6.调用异步函数再链式调用 catch 方法获取异步函数执行的错误信息
7.await 关键字只能出现在异步函数中
8.await promise await 后面只能写 promise 对象 写其他类型的 api 是不可以的
9.await 关键字可以暂停异步函数向下执行 直到 promise 返回结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const fs = require("fs");
const promisify = require("util").promisify; const readFile = promisify(fs.readFile);
async function run() { let r1 = await readFile("./1.txt", "utf8"); let r2 = await readFile("./2.txt", "utf8"); let r3 = await readFile("./3.txt", "utf8"); console.log(r1); console.log(r2); console.log(r3); } run();
|