一. 服务端开发
web服务器
能够提供web访问服务的机器就是网站服务器,能接收浏览器端的请求,能对请求做出响应。
IP地址
在互联网中电脑的唯一标识。例如:113.45.94.17。浏览器端请求服务器端的资源首先要有这台服务器的IP地址,
才能找到这台服务器。
如果将本机作为服务器,本机有一个特定的IP是 127.0.0.1
域名
由于IP地址难于记忆,所以产生了域名的概念,所谓域名就是平时上网所使用的网址。
IP地址与域名是对应的关系,在浏览器的地址栏中输入域名,会有专门的服务器 (DNS) 将域名解析为对应的IP地
址,从而找到对应的服务器。
如果将本机作为服务器,本机有一个特定的域名是 localhost
端口
通过IP地址找到对应的服务器以后,还需要指定端口来进一步确定访问的是当前服务器提供的什么服务。比如80是
apache服务默认占用的端口,3306是mysql服务占用的端口。
URL
统一资源定位符,是互联网上标准资源的地址。
请求与响应
二.创建web服务器
在NodeJs中不需要安装额外的软件充当网站服务器,NodeJs中提供的HTTP模块即可创建web服务器。
// 引用系统模块
const http = require(‘http’);
// 创建web服务器
const server = http.createServer();
// 当客户端发送请求的时候
server.on(‘request’, (req, res) => {
// 设置响应头
res.writeHead(200, {
‘Content‐Type’: ‘text/html;charset=utf8’
});
// 设置响应体
res.write(’
哈哈哈
');
// 结束请求
res.end();
});
// 监听3000端口
server.listen(3000, error => {
if (!error) {
console.log(‘服务器已启动,监听3000端口,请访问 localhost:3000’)
}
});
HTTP协议
超文本传输协议,用于从web服务器传输超文本到本地浏览器的传送协议,基于客户端服务器架构工作。
请求报文
请求方式
GET 请求数据
POST 发送数据
获取请求方式
req.method
获取请求地址
req.url
获取请求报文信息
req.headers
console.log(req.headers[‘accept’]);
请求地址
响应报文
HTTP状态码 :
200 请求成功
404 请求的资源没有被找到
500服务端错误
400客户端请求有语法错误
内容类型
text/html
text/css
res.writeHead(200, {
‘content-type’: ‘text/html;charset=utf8’
});
GET传参
参数被放置在地址栏中,格式为:name=zhangsan&age=20
// 处理get参数
const url = require(‘url’);
let { query } = url.parse(req.url, true);
POST传参
参数被放置在请求体中,格式和GET参数相同。
// 处理post参数
// 由于post传递的参数数据量比较大,在网络中并不是一次性传递完成的,而是分成了多次传递
// 所以在接收的时候也需要分为多次接收
// 在NodeJs中接收post参数需要使用事件完成
const querystring = require(‘querystring’);
let formData = ‘’;
req.on(‘data’, chunk => formData += chunk);
req.on(‘end’, () => console.log(querystring.parse(formData)));
路由
路由是指URL地址与程序的映射关系,更改URL地址可以改变程序的执行结果。简单说就是请求什么响应什么。
const http = require(‘http’);
const url = require(‘url’);
const finalhandler = require(‘finalhandler’)
// 创建网站服务器
const server = http.createServer();
// 当客户端发来请求的时候
server.on(‘request’, (req, res) => {
// 处理404方法
var done = finalhandler(req, res);
// 获取客户端的请求路径
let { pathname } = url.parse(req.url);
// 对请求路径进行判断 不同的路径地址响应不同的内容
if (pathname == ‘/’ || pathname == ‘/index’) {
res.end(‘index’);
}else if (pathname == ‘/list’) {
res.end(‘list’);
}else if (pathname == ‘/about’) {
res.end(‘about’);
}else {
// 如果以上路由都没有匹配上, 则进行404处理
done();
}
});
// 程序监听端口
server.listen(3000);
客户端请求方式
- 浏览器地址栏
- Form表单提交
- link标签的href属性
- script标签的src属性
- image标签的src属性
静态资源处理
服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如CSS、JavaScript、image文件。
使用Node.js的第三方模块serve-static处理静态资源的响应。
const http = require(‘http’);
const url = require(‘url’);
const path = require(‘path’);
const fs = require(‘fs’);
const mime = require(‘mime’);
const app = http.createServer();
app.on(‘request’, (req, res) => {
// 获取用户的请求路径
let pathname = url.parse(req.url).pathname;
pathname = pathname == '/' ? '/default.html' : pathname;
// 将用户的请求路径转换为实际的服务器硬盘路径
let realPath = path.join(__dirname, 'public' + pathname);
// 根据路径反回文件类型
let type = mime.getType(realPath)
// 读取文件
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
})
res.end(result);
});
});
app.listen(3000);
console.log(‘服务器启动成功’)
三.Node.js工作原理
同步异步
同步或者异步指的是服务器端处理请求的方式。
代码执行顺序
同步方式
代码一行一行执行,下一行的代码必须等待上一行代码执行完成以后才能执行.
异步方式
代码在执行过程中某行代码需要耗时,代码的执行不会等待耗时操作完成以后再去执行下一行代码,而是不等待直接
向后执行.异步代码的执行结果需要通过回调函数的方式处理.
Promise
Promise出现的目的是解决Node.js异步编程中回调地狱的问题
Promise本身是一个构造函数,要使用promise解决回调地狱的问题 需要使用new运算符创建Promise构造函数的
实例对象
在创建对象的时候需要传入一个匿名函数,匿名函数中有两个参数 resolve,reject
const fs = require(‘fs’);
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)
})
异步函数
异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌
套,使代码变得清晰明了
async
- 普通函数定义前加async关键字 普通函数变成异步函数
- 异步函数默认返回promise对象
- 在异步函数内部使用return关键字进行结果返回 结果会被包裹的promise对象中 return关键字代替了resolve
方法 - 在异步函数内部使用throw关键字抛出程序异常
- 调用异步函数再链式调用then方法获取异步函数执行结果
- 调用异步函数再链式调用catch方法获取异步函数执行的错误信息
await关键字 - await关键字只能出现在异步函数中
- await promise await后面只能写promise对象 写其他类型的API是不不可以的
- await关键字可是暂停异步函数向下执行直到promise返回结果
const fs = require(‘fs’);
// 改造现有异步函数api 让其返回promise对象 从而支持异步函数语法
const promisify = require(‘util’).promisify;
// 调用promisify方法改造现有异步API 让其返回promise对象
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();