likes
comments
collection
share

深入探索Koa框架:构建高效Node.js Web服务

作者站长头像
站长
· 阅读数 34

前言

     在Node.js中,如果我们要实现一个Web服务,那么我们就就必须要引入http模块,再创建一个Web服务,然后对端口进行监听.对此我们可以使用Koa框架方便我们创建一个Web服务,那么什么又是Koa呢?

Koa是一个基于Node.js平台的Web开发框架,由Express框架的创造者所开发。Koa的设计目标是提供一个更小、更富有表现力和更健壮的Web框架。它使用ES6的async/await功能来简化异步代码的编写,避免了回调地狱(Callback Hell)的问题,从而提高了代码的可读性和维护性。Koa并不在核心中捆绑任何中间件,而是提供一套优雅的函数库,允许开发者自由选择和组合中间件,这使得编写Web应用变得更加灵活和高效。

使用Koa

Koa对比原生Node.js

     首先我们先使用原生的Node.js创建一个Web服务。

// 使用原生的node实现一个Web服务,就必须要引入http模块
const http = require('http');

//创建一个Web服务,这里接受一个回调函数
const server = http.createServer((req,res)=>{
    // req 请求分为请求头 请求体  res响应
    res.end('hello world')
})

//监听
//这里也可以接受一个回调函数
server.listen(3000,()=>{
    console.log('3000 端口启动');
})

然后我们再安装Koa依赖

npm i koa

安装好依赖,创建文件demo1.js.我们使用Koa我们就需要引入Koa的模块const Koa = require('koa')然后new 一个Koa,因为其源码被写成了一个函数,所以我呢吧需要new.相较于原生的Node.js是使用响应体res向前端输出数据,那么在koa中又是如何实现的呢?在Koa中我们需要自定义一个函数,该函数接受一个参数ctx,这个参数就是Koa的上下文对象,使用这个上下文对象,我们能实现原生Node.js的所有用法,我们打印ctx

深入探索Koa框架:构建高效Node.js Web服务

深入探索Koa框架:构建高效Node.js Web服务

深入探索Koa框架:构建高效Node.js Web服务

它同样包含了自己封装的请求体育响应体,甚至原生Node.jsreq以及res.所以在Koa中使用ctx.res.end也可以实现数据挂载在前端页面,也可以使用Koa本身的ctx.response.body = 挂载内容',除了这两种方法也存在一种代理方法,直接使用ctx.body= 挂载内容'也可以实现挂载。为了使我们自定义的函数生效,我们必须使用New Koa返回的属性调用use方法

const Koa = require('koa');

//必须New Koa其源码被写成了一个函数
const app = new Koa();


//向全端输出内容 自定义一个函数,app.use()
//ctx 是Koa的上下文对象
//koa中的ctx集成了req 以及res
const main = (ctx)=>{
    console.log(ctx);
    // ctx.res.end = 'Hello world'  响应体挂数据
    // ctx.response.body = 'Hello World';
    ctx.body = 'Hello World';//代理 访问子对象中的body
    
}

app.use(main)

app.listen(3000,()=>{
    console.log('3000端口启动');
})

请求数据处理

     当前端向后端发送数据请求时,后端需要读取到前端请求数据的格式,在Koa中存在一个方法accepts()里面写数据格式,就可以读取到了

const Koa = require('koa');

//必须New Koa其源码被写成了一个函数
const app = new Koa();


//向全端输出内容 自定义一个函数,app.use()
//ctx 是Koa的上下文对象
//koa中的ctx集成了req 以及res
const main = (ctx)=>{
    if(ctx.request.accepts('xml')){
        //如果前端请求的是一个xml数据,则返回
        ctx.body = '<data>Hello World</data>'
    }else if(ctx.request.accepts('html')){//会读取到前端请求头中的accept属性
        //如果前端请求的是一个html数据,则返回
        ctx.body = '<p>Hello World</p>'
    }
}
 
app.use(main)

app.listen(3000,()=>{
    console.log('3000端口启动');
})

深入探索Koa框架:构建高效Node.js Web服务

假设我引入一个html文件呢? 这里我们就需要使用fs文件系统了,在html文件中我们事先写好

深入探索Koa框架:构建高效Node.js Web服务

const context = fs.readFileSync('./template.html','utf-8')

fs文件系统返回的是一个buffer流,但是浏览器是无法读取流这一个数据类型的,所以就会触发下载。为了浏览器能读取,我们就需要设置编码格式就好了。我们也可以换一种写法,我们创建一个可读流,设置请求头,或者使用ctx.response.type = 'html'也可以实现读取html文件

// ctx.response.type = 'html'  同理也可以用ctx.type
    ctx.res.writeHead(200,{'Content-Type':'text/html'})//也可以用原身的node写
    // 创建一个可读流  依旧是一个十六进制的buffer流
    const context = fs.createReadStream('./template.html')
    // console.log(context);
    ctx.body = context

路径处理

     

const main = (ctx)=>{
    //判断前端请求的路径
    if(ctx.url === '/'){
        ctx.type = 'html';
        ctx.body = '<h2>首页</h2>'
    }else {
        ctx.type = 'html';
        ctx.body = '<a href="/">去首页</a>'
    }
}

页面路径如果这样写的话,假设我们很多条数据,我们就必须写很多个if-else代码的可读性就会变差,所以在koa中也有路由的说法koa-route,我们先安装koa-route

npm i koa-route

引入koa-route

const router = require('koa-route');

实现路径的切换,在koa-route中有一个get('url',function)接受路径,以及执行函数。

const main = (ctx)=>{
    ctx.type = 'html'
    ctx.body = '<h2>首页</h2>'
}
 

const about = (ctx)=>{
    ctx.type = 'html'
    ctx.body = '<a href="/">关于首页,点击去首页</a>'
}
app.use(router.get('/',main))//第二参数写mian 默认main会生效
app.use(router.get('/about',about))

但是如果请求失败,我们又应该如何知道呢,这里我们就可以自己写一个日志生成,方便检查错误,但是

const logger = (ctx)=>{//后端日志输出  前端请求路径
    console.log(`${ctx.url}-${ctx.method}-${Date.now()}`);//日志,方便检查出错
}

app.use(logger)

如果这样写的话就会出问题,在koause一旦前面的use执行完成之后,就不会执行后续的use了,所以在自定义函数中,我们需要传入一个next方法,并调用

const Koa = require('koa');
const router = require('koa-route');
//必须New Koa其源码被写成了一个函数
const app = new Koa();


//向全端输出内容 自定义一个函数,app.use()
//ctx 是Koa的上下文对象
//koa中的ctx集成了req 以及res\
const logger = (ctx,next)=>{//后端日志输出  前端请求路径
    console.log(`${ctx.url}-${ctx.method}-${Date.now()}`);//日志,方便检查出错
    next()//在你完成你要的逻辑之后,需要调用next() 让下一个use生效
}
const main = (ctx)=>{
    ctx.type = 'html'
    ctx.body = '<h2>首页</h2>'
}
 

const about = (ctx)=>{
    ctx.type = 'html'
    ctx.body = '<a href="/">关于首页,点击去首页</a>'
}
// app.use(main)
//当浏览器
app.use(logger)//必须在路由之前
app.use(router.get('/',main))//第二参数写mian 默认main会生效
app.use(router.get('/about',about))




app.listen(3000,()=>{
    console.log('3000端口启动');
})

洋葱模型

     我们来看看app.use的执行过程

const Koa = require('koa');
const app = new Koa()

const one = (ctx,next)=>{ //中间件
    console.log(1);
    next()
    console.log(2);
}

const two = (ctx,next)=>{
    console.log(3);
    next()
    console.log(4);
}

const three = (ctx)=>{
    console.log(5);
    console.log(6);
}
app.use(one)
app.use(two)
app.use(three)

app.listen(3000,()=>{
    console.log('3000端口启动');
})

我们执行代码,终端会先输出1 3 5 6之后会输出什么呢? 我们来看看结果

深入探索Koa框架:构建高效Node.js Web服务

1 3 5 6 4 2. 是不是有点像递归先执行one中的第一个输出,遇见next后就执行下一个app.use当最后一个app.use执行完毕,就执行上一个app.use.所以app.use的实现原理就是递归,这一过程被称为洋葱模型

感谢大家阅读本文,若有不足,恳请指出,谢谢大家!!!

深入探索Koa框架:构建高效Node.js Web服务

转载自:https://juejin.cn/post/7390815289993560118
评论
请登录