Koa2基础笔记

news2024/11/27 18:22:55

目录

一、快速入门

二、中间件

链式调用

洋葱圈模型

异步处理

三、路由

koa-router

四、请求参数解析

处理URL参数

处理body参数

 五、错误处理

原生的错误处理

使用中间件


一、快速入门

新建文件夹使用VSCode打开,终端运行npm init -y生成package.json配置文件。安装koa,npm i koa。编写服务程序:src/start.js

1.导入koa包 2.实例化app对象 3.编写中间件 4.启动服务,监听3000端口

// 1.导入koa
const Koa=require('koa')
// 2.实例化对象
const app=new Koa()
// 3.编写中间件
app.use((ctx)=>{
    // ctx:context http请求的上下文(ctx.request:http请求 + ctx.response:http响应)
    ctx.body='hello koa2'
})
// 4.启动服务,监听3000端口
app.listen(3000,()=>{
    console.log('server is running on http://localhost:3000');
})

运行 node src/start.js 成功后显示http://localhost:3000

安装nodemon:npm i nodemon -D,运行 nodemon src/start.js。改变代码自动重启。

二、中间件

在请求和响应中间的处理程序;将从请求到响应的业务拆开成多个功能独立的函数,就是中间件;对于处理请求来说,在响应发出之前,可以在请求和响应之间做一些操作,并且将这个处理结果传递给下一个函数继续处理(类似工厂流水线)。

const Koa=require('koa')
const app=new Koa()
// 中间件
//简写可以省略app,写成app.use().use().use()
//在app.use中只能接收一个参数作为函数
app.use((ctx,next)=>{
    console.log('头部');
    next()
})
app.use((ctx,next)=>{
    console.log('身体');
    next()
})
app.use((ctx)=>{
    console.log('尾部');
    ctx.body='组装完成'
})
app.listen(3000,()=>{
    console.log('server is running on http://localhost:3000');
})

链式调用

app.use(function) 将给定的中间件方法添加到此应用程序;app.use()返回this,因此可以链式表达

洋葱圈模型

const Koa=require('koa')
const app=new Koa()
app.use((ctx,next)=>{
    console.log('1');
    next()
    console.log('2');
}).use((ctx,next)=>{
    console.log('3');
    next()
    console.log('4');
}).use((ctx,next)=>{
    console.log('5');
    ctx.body='处理完成'
})
// 输出 1 3 5 4 2
app.listen(3000,()=>{
    console.log('server is running on http://localhost:3000');
})

异步处理

依靠async await语法;async声明异步函数,await后跟promise对象。加了async的函数返回值会变为一个Promise对象

const Koa=require('koa')
const app=new Koa()
app.use(async (ctx,next)=>{
//middleware1中构造一个message=aa
    ctx.message='aa'
    await next()
//返回最终数据
    ctx.body=ctx.message
}).use(async (ctx,next)=>{
//middleware2中同步追加bb
    ctx.message+='bb'
    await next()
}).use(async (ctx)=>{
//middleware3中异步追加cc
    const res=await Promise.resolve('cc')
    ctx.message+=res
})
// 输出 aabbcc
app.listen(3000,()=>{
    console.log('server is running on http://localhost:3000');
})

三、路由

路由就是建立URL和处理函数之间的对应关系,用于根据不同的methods和URL返回不同的内容。

例如:使用postman测试接口,http://localhost:3000/users、GET方法返回’这是用户页’。

const Koa=require('koa')
const app=new Koa()
app.use((ctx)=>{
    // 编写时也可以省略request和response,直接写ctx.url ctx.body
    if(ctx.request.url=='/'){
        ctx.response.body='这是主页'
    }else if(ctx.request.url=='/users'){
        if(ctx.request.method=='GET')
            ctx.response.body='这是用户页'
        else if(ctx.request.method=='POST')
            ctx.response.body='创建用户'
        else
        ctx.response.status=405
    }else{
        ctx.response.status=404
    }
})
app.listen(3000)

koa-router

安装 npm i koa-router。使用:1.在koa的基础上导入koa-router包 2.实例化router对象 3.使用router处理路由 4.注册中间件

// 1.导入koa
const Koa=require('koa')
// 2.实例化对象
const app=new Koa()
// 3.使用koa-router
const Router=require('koa-router')
const router=new Router()
router.get('/',(ctx)=>{
    ctx.body='这是主页'
})
router.get('/users',(ctx)=>{
    ctx.body='这是用户页'
})
router.post('/users',(ctx)=>{
    ctx.body='创建用户'
})
// 4.注册中间件
app.use(router.routes())
// 支持返回405和501的错误
app.use(router.allowedMethods())
// 5.启动服务,监听3000端口
app.listen(3000,()=>{
    console.log('server is running on http://localhost:3000');
})

优化:

将一个模块放在单独的文件中,分离出一个router路由层。

1.创建src/router/user.route.js

2.将上面有关路由部分的代码放入此文件并进行导出module.exports=router

3.并在原文件中导入

const userRoute=require('./router/user.route')

app.use(userRoute.routes()).use(userRoute.allowedMethods())

四、请求参数解析

后端需要解析请求的参数,作为数据库操作的条件。接口设计:

1.获取对应id的用户信息GET/user/:id

2.查询年龄18-20的用户信息 GET/users?start=18&end=20

3.解析注册信息保存至数据库 POST/users{name:’a’,age:22}

对于不同的http请求,需要使用不同的方式携带参数;get请求在URL中以键值对传递,post/put/patch/delete请求在请求体中传递。

处理URL参数

1.query:在GET请求中,如果以键值对的形式传参,可以通过query得到。

2.params:在GET请求中,有些参数可以通过路由传参,可以通过params得到。

// 1.导入koa
const Koa=require('koa')
// 2.实例化对象
const app=new Koa()
// 3.使用koa-router
const Router=require('koa-router')
// 统一前缀
const router=new Router({prefix:'/users'})
const db=[
    {id:1,name:'a',age:18},
    {id:2,name:'b',age:20},
    {id:3,name:'c',age:22},
]
// 获取对应年龄的用户信息
router.get('/',(ctx)=>{
    // 赋默认值,值为空时不会出错
    const {start=0,end=0}=ctx.query //ctx.request.query
    const res=db.filter((item)=>item.age>=start&&item.age<=end)
    res.length==0?ctx.throw(404):(ctx.body=res)
})
// 获取对应id的用户信息
router.get('/',(ctx)=>{
    const id=ctx.params.id
    const res=db.filter((item)=>item.id==id)
    // 找不到id 抛出错误
    if(!res[0]) ctx.throw(404)
    ctx.body=res[0]
})
router.post('/',(ctx)=>{
    ctx.body='创建用户'
})
// 4.注册中间件
app.use(router.routes())
// 支持返回405和501的错误
app.use(router.allowedMethods())
// 5.启动服务,监听3000端口
app.listen(3000,()=>{
    console.log('server is running on http://localhost:3000');
})

处理body参数

安装koa-body或koa-bodyparser,npm i koa-body

// 1.导入koa
const Koa=require('koa')
// 引入类要实例化,此处是函数,所以不需要
const { koaBody } = require('koa-body');
// 2.实例化对象
const app=new Koa()
// 在所有中间件注册前注册KoaBody
app.use(koaBody())
// 3.使用koa-router
const Router=require('koa-router')
// 统一前缀
const router=new Router({prefix:'/users'})
const db=[
    {id:1,name:'a',age:18},
    {id:2,name:'b',age:20},
    {id:3,name:'c',age:22},
]
router.post('/',(ctx)=>{
    db.push(ctx.request.body)
    ctx.body=db
})
// 4.注册中间件
app.use(router.routes())
// 支持返回405和501的错误
app.use(router.allowedMethods())
// 5.启动服务,监听3000端口
app.listen(3000,()=>{
    console.log('server is running on http://localhost:3000');
})

 五、错误处理

原生的错误处理

一般Koa中的错误分三类

1.404,当请求的资源找不到,或者没有通过ctx.body返回时,由koa自动返回。

2.手动抛出,通过ctx.throw手动抛出。

3.500,运行错误

Koa类是继承Node的Emitter类,因此可以通过emit提交一个错误,通过on进行统一错误处理。

// 1.导入koa
const Koa=require('koa')
// 引入类要实例化,此处是函数,所以不需要
const { koaBody } = require('koa-body');
// 2.实例化对象
const app=new Koa()
// 在所有中间件注册前注册KoaBody
app.use(koaBody())
// 3.使用koa-router
const Router=require('koa-router')
// 统一前缀
const router=new Router({prefix:'/users'})
router.get('/:id/article/:aid',(ctx)=>{
    console.log(ctx.params);
    if(false){
        ctx.body={id:1,title:'文章1',content:'文章1'}
    }else{
        return ctx.app.emit('error',{code:404,message:'Resource is not found'},ctx)
    }
})
// 4.注册中间件
app.use(router.routes())
// 支持返回405和501的错误
app.use(router.allowedMethods())
app.on('error',(err,ctx)=>{
    console.error(err)
    ctx.body=err
})
// 5.启动服务,监听3000端口
app.listen(3000,()=>{
    console.log('server is running on http://localhost:3000');
})

使用中间件

安装 npm i koa-json-error

基础用法

const Koa=require('koa')
const app=new Koa()
// 注册并使用
const error=require('koa-json-error')
app.use(error())
app.use((ctx)=>{
    ctx.body='a'
})
app.listen(3000)

高级用法

const Koa=require('koa')
const app=new Koa()
// 注册并使用
const error=require('koa-json-error')
app.use(error({
    format:(err)=>{
        return {code:err.status,message:err.message,result:err.stack}
    },
    // obj是format的对象,将format返回的三个值解构
    postFormat:(err,obj)=>{
        const {result,...rest}=obj
        // 生产环境只返回code和message,开发环境下将错误堆栈result也一并返回
        // 要实现功能,需安装npm i cross-env,配置package.json文件:
        // "scripts":{
        //     "dev":"nodemon src/index.js"
        //     "prod":"NODE_ENV=production node src/index.js"
        // }
        // 生产环境运行npm run prod 开发环境运行npm run dev
        return process.env.NODE_ENV=='production'?rest:obj
    }
}))
app.use((ctx)=>{
    ctx.body='a'
})
app.listen(3000)

(视频:B站杰哥课堂)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/51562.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]计算机毕业设计springboot水果管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

冬季寒冷,普通空调如何做到智能控制,增温又降耗的?

寒冷的冬日总少不得取暖的工具&#xff0c;空调成为人们的优先选择。但是&#xff0c;在办公大楼、商场等需要长时间空调供暖&#xff0c;空调又多的地方&#xff0c;空调控制让不少人感觉到了困扰。上下班时间空调多&#xff0c;检查慢&#xff0c;如果漏掉其中一个&#xff0…

C++——类和对象讲解

C——类和对象讲解总览 本篇文章的讲解将按照上述的方式&#xff0c;逐层递进&#xff0c;进一步帮你拿捏C类和对象这部分。 类和对象上&#xff08;基础篇&#xff09; 1、初识面向对象编程&#xff1a; 初步了解面向过程和面向对象的区别 举个比较感人的例子用来帮助铁子…

Qt视频监控系统一个诡异问题的解决思路(做梦都想不到)

一、前言 由于Qt版本众多&#xff0c;几百个版本之间存在不兼容的情况&#xff0c;为此如果要兼容很多版本&#xff0c;没有取巧的办法和特殊的捷径&#xff0c;必须自己亲自安装各个版本编译运行并测试&#xff0c;大问题一般不会有&#xff0c;除非缺少模块&#xff0c;小问…

健壮性测试是什么?

当大多数人开车时&#xff0c;他们不会担心刹车失灵。当他们的孩子得到一个新玩具时&#xff0c;他们也不担心因故障受伤。事实上&#xff0c;大多数人在日常生活中根本不担心系统故障。 这是因为软件开发人员或质量控制工程师已经解决了质量问题。如果目标是交付高质量、可靠…

基础:html5、html、htm、xhtml、dhtml、shtml、shtm、xml、xsl、xslt

一、理解 1.1、HTML5&#xff08; HyperText Markup Language 5 &#xff09; HTML5_百度百科 HTML5 技术结合了 HTML4.01 的相关标准并革新&#xff0c;符合现代网络发展要求&#xff0c;在 2008 年正式发布。HTML5 由不同的技术构成&#xff0c;其在互联网中得到了非常广泛…

TCP/IP五层协议栈(2)

1.传输层协议(TCP传输的机制补充) 1.1.滑动窗口 滑动窗口存在的意义就是在保证可靠性的前提下,尽量提高传输效率. 由于TCP是得保证可靠传输的,所以每一次数据发送时都需要等待对方的ACK.大部分时间都用在等ACK上,而确认应答是可靠传输的主要机制又不能不等.所以有了新的机制…

JavaScript -- 多种类型转换方法总结

文章目录类型转换1 转换为字符串2 转换为数值3 转换为布尔值4 总结类型转换 类型转换指将一种数据类型转换为其他类型 类型转换是根据当前值去创建另一个值&#xff0c;而不是将当前值直接进行转换 这里说到的转换都是显示类型转换&#xff0c;除此之外还有隐式类型转换 1 转…

MnTTS: 开源蒙古语语音合成数据集及其基线模型

本次分享内蒙古大学蒙古文信息处理重点实验室、蒙古文智能信息处理技术国家地方联合工程研究中心及语音理解与生成实验室 (S2LAB) &#xff08;https://ttslr.github.io/index_S2Group.html&#xff09;共同发布的开源蒙古语语音合成数据集及其基线模型。相关论文《MnTTS: An O…

BI业务用户商业分析新时代,如何把数据用透?

数字化转型进入实质性阶段&#xff0c;企业对于数据的需求也随之加深。然而&#xff0c;一些企业积累了大量数据&#xff0c;却难以深度释放数据价值。 近几年&#xff0c;作为数据应用的有力工具&#xff0c;BI商业智能分析平台同样进入了转折期&#xff0c;其发展趋势明显呈…

Nacos后台系统未授权添加管理员

一&#xff1a;什么是nacos Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集&#xff0c;帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。 Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中…

爱奇艺:基于龙蜥与 Koordinator 在离线混部的实践解析 | 龙蜥技术

在 2022 云栖大会龙蜥峰会云原生专场上&#xff0c;来自爱奇艺的基础架构研究员赵慰分享了《基于龙蜥与 Koordinator 的在离线混部实践》技术演讲&#xff0c;以下为本次演讲内容&#xff1a; 一、爱奇艺离线业务混部背景 与众多互联网公司一样&#xff0c;爱奇艺常见的负载…

Go语言学习笔记-A Tour of Go 练习笔记-Images

Exercise: Images 练习题目: Remember the picture generator you wrote earlier? Lets write another one, but this time it will return an implementation of image.Image instead of a slice of data. Define your own Image type, implement the necessary methods, …

您的推特营销选对群控了吗

作为跨境电商从业者&#xff0c;我们都知道&#xff0c;如果平台检测到违规&#xff0c;最多的是多账号关联。平台怎么判定我们的账号是否关联呢&#xff1f;一个重要的依据是浏览器的指纹信息。 一、进行站外引流的困难有哪些&#xff1a; 国内用户在推广海外社交媒体时&…

【OpenCV-Python】教程:3-10 直方图(4)直方图反向投影

OpenCV Python 直方图 反向投影 【目标】 直方图反向投影calcBackProject 【原理】 用于图像分割和查找感兴趣目标。简单的说&#xff0c;会创建一个与输入图像同样大小的图像&#xff08;单通道&#xff09;&#xff0c;每个像素对应像素属于目标的概率。更简单的说就是&am…

pdf文件丢失怎么办?别慌,详细介绍4种恢复方法

pdf文件丢失怎么找到&#xff1f;别慌&#xff0c;停止往电脑上写入新的内容&#xff0c;重要的事情说三遍&#xff01;下面&#xff0c;我们将会向您详细介绍在pdf文件丢失后的多种方法&#xff0c;请继续阅读以获得更多帮助&#xff01; 方法1.运用Windows搜索功能 很多时候…

运放参数-共模输入范围-运算放大器

运放共模输入范围 根据实际的应用我们会选择一个运算放大器&#xff08;op amp&#xff09;&#xff0c;选型过程中工程师会考虑一些参数可例如&#xff1a;电源电压、增益带宽积、输入共模范围、转换速率和输入噪声电压等等。 在本篇文章中重点介绍了运放的输入共模范围的定…

Codeforces Round #724 (Div. 2) C. Diluc and Kaeya

翻译&#xff1a; 蒙德施塔特一个酒庄帝国的大亨&#xff0c;在任何方面都无可匹敌。法佛尼乌斯骑士团中具有异域外表的思想家。 这一次&#xff0c;兄弟俩要处理的是一块刻着他们名字的奇怪木头。这块木板可以表示为一串&#x1d45b;字符。每个字符不是“D”就是“K”。您希…

Activiti7工作流(一)

工作流介绍 工作流(Workflow)&#xff0c;就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程&#xff0c;从而实现某个预期的业务目标&#xff0c;或者促使此目标的实现”。 案例: 出差费…

视频编解码 — 码控算法

目录 码控算法 码控算法的类型 具体操作过程如下 复杂度求解 帧组级 帧级 GOM级 码控算法 用算法来控制编码器输出码流的大小&#xff0c;码控就是为一帧图像选择一个合适的QP值的过程。 一帧图像的画面确定了之后&#xff0c;画面的复杂度和QP值几乎决定了编码之后的…