700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Node.js服务器端开发

Node.js服务器端开发

时间:2022-05-07 07:44:53

相关推荐

Node.js服务器端开发

创建nodejs服务器的步骤:

1、导入http模块

2、创建http服务器对象

3、给服务器对象注册(绑定)request事件

(1)对不同请求方式进行处理

(2)路由:对不同的请求路径进行处理

(3)处理请求参数

(4)给客户端发送响应信息

app.on('request',(req,res)=>{

})

4、开启端口监听

我们今天就按照这个步骤来学习nodejs服务器的知识。

一、NodeJS服务器开发

1、学习服务器开发的目的

可以和后端程序员进行紧密的配合让业务前置

扩展知识面

2、服务器的主要工作

实现项目的业务逻辑实现数据的增删改查(CRUD)

3、使用Node创建服务器示例

引入http模块创建服务器对象定义请求和响应监听端口号 本地机的域名:localhost 本地机的IP地址:127.0.0.1

//1、引入http模块const http= require('http');//2、创建Web服务器对象const app=http.createServer()//3、定义请求和响应/* 回调函数中的参数req(request):表示请求对象,存放了客户端的所有请求信息 res(respone):表示响应对象,服务器端通过该对象向客户端发送响应信息*/app.on('request',(req,res)=>{res.end('Hello Word')res.writeHead(200,{// 'content-type':'text/plain'//相应信息是纯文本格式'content-type':'text/html;charset=utf8'//相应信息是纯文本格式})});//4、监听端口号:指定服务器所使用的端口号app.listen(8080)//监听3000端口console.log('服务器已启动,监听8080端口,请访问localhost:8080');//127.0.0.1 本地机的IP地址

4、http协议

HTTP(Hyper Text Transfer Protocol)超文本传输协议

HTTP协议规定了如何从网站服务器传输超文本到本地浏览器HTTP协议基于客户端服务器架构工作,是客户端(用户)和服务器端(网站)请求和应答的标准HTTP协议可以使浏览器更加高效,使网络传输减少HTTP协议不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。

5、关于http请求和响应

请求消息:客户端向服务器端发送请求时所携带的数据块响应消息:服务器端响应客户端请求时所携带的数据块客户端向服务器端发送请求的类型

⭐get请求:在浏览器的地址栏直接输入请求地址或在页面使用超链接(a标签)发起的请求,默认都是get请求

⭐post请求:在<form>标签的method属性中指定为post时,请求方式就是post

get请求 :

post请求:

get请求和post请求的区别

⭐get请求的参数是通过URL进行传递。post请求的参数包含在请求体中

⭐get请求不安全,不能用来传输敏感信息;post请求相对比较安全

⭐get请求在url中传递的参数是有长度限制的(不同的浏览器限制的长度不同),post请求对长度没有限制

⭐get请求参数会被完整的保留在浏览器的历史记录中;post请求参数不会再浏览器中保留

⭐get请求使用url编码(百分号编码);post请求支持多种编码方式。

⭐get请求在浏览器中可以被主动缓存(cache);post请求不会

⭐get请求在浏览器回退时是无害的;post请求在浏览器回退时会再次向服务器提交数据

⭐get请求时浏览器会把请求头(http header)和数据(data)一起发送出去;

⭐post请求时浏览器会先发送请求头(http header),服务器响应后(状态码100),浏览器会再次发送数据(data),服务器器会给客户端返回状态码200

服务器收到用不同请求方式发送的请求时,如何分开处理(服务器如何区分get请求和post请求)通过对请求对象(request)的method属性进行判断,来获取用户的请求方式

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥服务器端代码

//1、引入http模块const http= require('http');const { homedir, hostname } = require('os');//2、创建Web服务器对象const app=http.createServer()//3、定义请求和响应/* 回调函数中的参数req(request):表示请求对象,存放了客户端的所有请求信息 res(respone):表示响应对象,服务器端通过该对象向客户端发送响应信息*/app.on('request',(req,res)=>{if(req.method == 'POST'){res.end('post')}else if(req.method == 'GET'){res.end('get')}console.log('请求方式:',req.method);console.log(req.headers['host']);//设置响应头信息res.writeHead(200,{// 'content-type':'text/plain'//相应信息是纯文本格式'content-type':'text/html;charset=utf8'//相应信息是纯文本格式})res.end('<h1>你好我是服务器端</h1>')//end()方法:断开与客户端的联系同时向客户端发送信息});//4、监听端口号:指定服务器所使用的端口号app.listen(8080)//监听3000端口console.log('服务器已启动,监听8080端口,请访问localhost:8080');//127.0.0.1 本地机的IP地址

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥HTML页面(使用get请求)

<!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><form action="http://localhost:8080" method="get"><label>用户名:<input type="text" name="username"></label><br><br><label>密码:<input type="password" name="pwd"></label><br><br><button type="submit">登录</button></form></body></html>

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥HTML页面(使用post请求)

<!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><form action="http://localhost:8080" method="post"><label>用户名:<input type="text" name="username"></label><br><br><label>密码:<input type="password" name="pwd"></label><br><br><button type="submit">登录</button></form></body></html>

根据客户端的请求地址访问不同的内容,通过对请求对象(request)的url属性来获取用户的请求地址

//1、引入http模块const http= require('http');//2、创建Web服务器对象const app=http.createServer()//3、定义请求和响应app.on('request',(req,res)=>{let url = req.url //获取客户端的请求地址if(url == '/index'||url=='/'){//'/'表示服务器的根目录res.end('<h1>Home Page</h1>')}else if(url=='/list'){res.end('<h1>List Page</h1>')}else{res.end('<h1>Not Found</h1>')}});//4、监听端口号:指定服务器所使用的端口号app.listen(8080)//监听3000端口console.log('服务器已启动,监听8080端口,请访问localhost:8080');

获取请求头信息

⭐请求头是请求信息的一部分,是由客户端浏览器自动发送给服务器的

⭐请求头的详细信息

格式:以键值对的方式保存属性

User-Agent:发送请求的浏览器的类型

Accept:服务器响应消息的格式

Accept-Language:客户端可以接收的语言

Accept-Encoding:客户端可以接收的编码压缩格式

Accept-Charset:可接收的应答的字符集

Host:请求的主机名

connection:连接方式(close 或keepalive)

获取请求头信息的方法req.headers

响应消息

⭐状态码

1**:请求已接收,需要继续处理2**:请求已成功被服务器接收、理解 (200:表示请求响应成功)3**:为完成请求,客户端需进一步细化请求4**:客户端的请求有错误 (404:请求的服务器资源不存在)5**:服务器端出现错误 (500:服务器程序有语法错误 )

⭐响应内容的类型(Content-Type)

text/plain:返回纯文本格式的内容text/html:返回HTML格式text/css:返回CSS格式application/javascript:返回JavaScript格式image/jpeg:返回JPEG图片格式application/json:返回JSON代码格式

二、HTTP请求和响应的处理

1、get请求参数的处理

get参数是放在浏览器的地址栏中发送的(即请求参数和url绑在一起)get参数的获取方式

⭐通过请求对象(req)的url属性获取客户端请求的URL(req.url)

⭐使用Node的内置模块url对请求地址进行解析,获取请求参数

let { query,pathname } = url.parse(clientURL,true)

const url =require('url')const http= require('http')const app = http.createServer()app.on('request',(req,res)=>{// 1、获取客户端请求let clientURL = req.urlconsole.log(clientURL);//2、解析urllet { query,pathname } = url.parse(clientURL,true)console.log('请求参数:',query);console.log('请求路径:',pathname);res.writeHead(200,{'content-type':'text/html;charset=utf8'})//3、对请求进行判断if(pathname=='/index'||pathname=='/'){res.end('<h1>hello '+query.username+'</h1>')}else if(pathname == '/list'){res.end('<h1>List Page</h1>')}else{res.end('<h1>Not Found</h1>')}})app.listen(8089)console.log('服务器已启动,运行在8089端口上...');

2、post请求参数的处理

post请求参数放在请求体中,而不是放在url中post参数的获取方式

⭐导入Node的内置模块querystring,将post请求参数转换成对象

⭐给请求对象(req)注册'data'事件,用于监听参数的传输,将传输的参数读取出来

⭐给请求对象(req)注册'end'事件,用于监听参数传输完毕,该事件被触发表明参数传递完成就可以对参数进行处理

⭐强调:关于querystring被弃用的解决办法

使用querystringify模块替代querystring模块。因为querystringify模块不是Node的内置模块,需要安装 npm install querystringify -g

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥服务器端代码

//导入系统模块querystring用于POST请求参数转化为对象格式const qs = require('querystringify')const http = require('http')const { fstat } = require('fs')const { error } = require('console')const app = http.createServer()app.on('request', (req, res) => {let postParams = '' //用来存储post请求参数//给req注册'data'事件,监听参数传递req.on('data',(params)=>{ //params表示请求参数,参数的传递是以字符流的方式进行的postParams += params})//给req注册'end'事件,该事件被触发表明参数传递完成req.on('end',()=>{console.log('获得的参数:',postParams)let temp = qs.parse(postParams)console.log('解析后的参数:',temp)console.log('用户名:',temp.username)console.log('密码:',temp.pwd)})res.end('ok')})app.listen(8090)console.log('服务器已启动,运行在8090端口上...');

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥客户端代码

<!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><style>div{width:500px ;margin: 100px auto;}</style><body><div><form action="http://localhost:8090" method="post"><label>用户名:<input type="text" name="username"></label><br><br><label>密&nbsp;&nbsp;&nbsp;码:<input type="password" name="pwd"></label><br><br>&nbsp;&nbsp;&nbsp;<button type="submit">提交</button>&nbsp;&nbsp;&nbsp;<button type="reset">重置</button></form></div></body></html>

3、路由

路由是指客户端请求地址与服务器端程序代码的对应关系。用户在浏览器地址栏中输入不同的请求地址,服务器端会为客户端响应不同的内容。

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥服务器端代码

const url =require('url')const http= require('http')const path = require('path')//用于路径的拼接const fs = require('fs')//用于读取文件const mime = require('mime') //引入第三方文件const app = http.createServer()app.on('request',(req,res)=>{//1、获取用户的请求方式const method = req.method.toLowerCase()//2、解析用户的请求地址const pathname = url.parse(req.url).pathname//3、设置响应头信息res.writeHead(200,{'content-type':'text/html;charset=utf8'})//4、进行路由if(method == 'get'){if(pathname == '/'||pathname == '/index'){let msg = '<h1>欢迎来到首页</h1>'+'<p>你的请求方式是:get</p>'res.end(msg)}else if(pathname == '/list'){let msg = '<h1>欢迎来到列表页</h1>'+'<p>你的请求方式是:get</p>'res.end(msg)}else{let msg = '<h1>你访问的页面不存在</h1>'+'<p>你的请求方式是:get</p>'res.end(msg)}}else if(method == 'post'){if(pathname == '/'||pathname == '/index'){let msg = '<h1>欢迎来到首页</h1>'+'<p>你的请求方式是:host</p>'res.end(msg)}else if(pathname == '/list'){let msg = '<h1>欢迎来到列表页</h1>'+'<p>你的请求方式是:host</p>'res.end(msg)}else{let msg = '<h1>你访问的页面不存在</h1>'+'<p>你的请求方式是:host</p>'res.end(msg)}}})app.listen(8090)console.log('服务器已启动,运行在8090端口上...');

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥get请求演示

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥客户端代码(post请求)

<!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><style>div{width:500px ;margin: 100px auto;}</style><body><div><form action="http://localhost:8090" method="post"><label>用户名:<input type="text" name="username"></label><br><br><label>密&nbsp;&nbsp;&nbsp;码:<input type="password" name="pwd"></label><br><br>&nbsp;&nbsp;&nbsp;<button type="submit">提交</button>&nbsp;&nbsp;&nbsp;<button type="reset">重置</button></form></div></body></html>

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥post请求演示

静态资源的访问

⭐静态资源:是指客户端向服务器端请求的资源,服务器端不需要处理,可以直接响应给客户端的资源。

⭐静态资源的类型:CSS、JavaScript、image文件,以及HTML文件

⭐动态资源:指的是相同的请求地址可以传递不同的请求参数,得到不同的响应资源

⭐访问过程:

创建一个文件夹用于存放静态资源获取用户的请求路径使用path模块对请求路径进行转换(将请求路径转换成静态资源对应的硬盘路径)使用mime模块获取静态资源的类型使用fs模块读取静态资源文件将读取的静态资源响应给用户

const http = require('http')const mime =require('mime')const url = require('url')const path = require('path')const fs = require('fs')const app = http.createServer()app.on('request', (req, res) => {//1、获取用户的请求路径let pathname = url.parse(req.url).pathnamepathname = pathname == '/' ? '/default.html' : pathname //判断用户是否请求了静态资源//2、将用户的请求路径转化成实际服务器硬盘路径let realPath = path.join(__dirname, 'public' + pathname)//3、利用mime模块根据路径返回响应资源的类型let type = mime.getType(realPath)//4、读取文件fs.readFile(realPath, (error, result) => {if (error != null) { //如果文件读取失败//指定返回资源的文件编码res.writeHead(404, { 'content-type': 'text/html;charset=utf8' })res.end('文件读取失败')} else { //如果文件读取成功res.writeHead(200, { 'content-type': type })res.end(result)}})})app.listen(8090)console.log('服务器已启动,运行在8090端口上...');

三、Node.js的异步编程

1、同步API

只有在当前的API执行完成后,才执行下一个API。代码的执行方式是按代码的先后顺序从上到下一行一行的执行

2、异步API

当前API的执行不会阻塞后续代码的执行。代码执行方式是当执行到耗时代码时,不等待,而是往后执行,执行结果由回调函数处理

function getMsg(callback){//函数的定义setTimeout(function(){callback({msg:'hello node.js'})//对callback函数的调用},2000)}getMsg(function(data){console.log(data);})//getMsg函数的调用

运行后需要等待2秒钟 才会打印结果

3、回调地狱

如果异步API后面代码的执行依赖当前异步API的执行结果,这就需要把代码写在回调函数中。一旦回调函数的嵌套层次过多,就会导致代码不易维护,我们将这种代码形象地称为回调地狱。

function getMsg(callback){//函数的定义setTimeout(function(){// callback({msg:'hello node.js'})//对callback函数的调用setTimeout(function(){setTimeout(function(){setTimeout(function(){callback({msg:'hello node.js'})},2000)},2000)},2000)},2000)}getMsg(function(data){console.log(data);})//getMsg函数的调用

运行后需要等待8秒钟 才会打印结果

4、回调地狱的解决方法

利用Promise解决回调地狱问题

Promise本身是一个构造函数,如果要使用Promise解决回调地狱的问题,需要使用new关键字

创建Promise构造函数的实例对象。

// 定义Promise

let promise = new Promise((resolve, reject) => { });

resolve:是一个函数

reject:是一个函数

promise.then(result => console.log(result))

.catch(error => console.log(error));

什么时候用?在程序中出现回调函数嵌套时,建议使用Promise对象

//依次读取a、b、c三个文件const fs = require('fs')fs.readFile('txt/a.txt','utf8',(err,result1)=>{console.log(result1);fs.readFile('txt/b.txt','utf8',(err,result2)=>{console.log(result2);fs.readFile('txt/c.txt','utf8',(err,result3)=>{console.log(result3);})})})

const fs = require('fs')function p1() {let promise = new Promise((resolve, reject) => { //创建promise对象fs.readFile('txt/a.txt', 'utf8', (err, result) => {if (err != null) {//若读取文件失败,则通过reject函数将错误信息传递出去reject(err)}resolve(result)})})return promise}function p2() {let promise = new Promise((resolve, reject) => { //创建promise对象fs.readFile('txt/b.txt', 'utf8', (err, result) => {if (err != null) {//若读取文件失败,则通过reject函数将错误信息传递出去reject(err)}resolve(result)})})return promise}function p3() {let promise = new Promise((resolve, reject) => { //创建promise对象fs.readFile('txt/c.txt', 'utf8', (err, result) => {if (err != null) {//若读取文件失败,则通过reject函数将错误信息传递出去reject(err)}resolve(result)})})return promise}//resole函数用来处理回调成功的结果,该函数将结果传递给then//reject函数用来处理回调失败的结果,该函数将结果传递给catchp1().then((result1) => { console.log(result1); return p2() }).then((result2)=>{console.log(result2);return p3()}).then((result3)=>{console.log(result3);}).catch((err) => { console.log(err); })

5、异步函数

异步函数实际上是在Promise对象的基础上进行了封装,它把一些看起来比较繁琐的代码封装起来,然后开放一些关键字供开发者来使用.异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了。

⭐async关键字:在函数定义放在函数的前面,标识该函数是一个异步调用函数,其返回值是一个Promise对象

⭐await关键字:可以暂停异步函数的执行,等待Promise对象返回结果再向下执行函数只能出现在异步函数中,await后面只能写Promise对象,不能写其他类型API使异步函数调用后,得到一个同步的效果

async function fn(){// throw '发生错误' //实际等价于返回的是reject(123)return 123 //实际等价于返回的是resolve(123)}fn().then((data)=>{ //调用fn函数,将该函数的返回值传递给then的回调函数console.log(data);}).catch((err)=>{//catch的回调函数接受的fn函数中throw抛出的异常信息console.log(err);})

♥♥♥♥♥♥♥♥对上述依次读取文件案例进行改造

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥要安装npm模块及promisify模块

安装npm模块 :npm install

安装promisify模块: npm installpromisify

const fs = require('fs')const { promisify } = require('util')//1、将fs.readFile函数进行转化,使它的返回值是一个Promise对象,需要使用util模块Promiseify函数const readFile = promisify(fs.readFile)async function p1(){let r1 = await readFile('txt/a.txt','utf8')let r2 = await readFile('txt/b.txt','utf8')let r3 = await readFile('txt/c.txt','utf8')console.log(r1);console.log(r2);console.log(r3);}p1()

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。