[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fhwzNf6GZb8D1ckF4eIrK9v464uf2PujxWy3yxjEJkqg":3},{"code":4,"message":5,"data":6},200,"成功",{"id":7,"createdAt":8,"title":9,"content":10,"summary":11,"image":12,"uid":13,"user":14,"categoryId":21,"category":22,"subCategoryId":24,"subCategory":25,"comments":27,"status":17,"reason":28,"notice":28,"visitCount":29,"commentCount":30,"keywords":31},137,"2024-11-11T17:14:50.497Z","Koa后端小项目编程记录（二）get、post请求","## 一、前言\n在上一章“项目搭建”：[https://www.xinwei.ltd/article/132](https://www.xinwei.ltd/article/132)中，我们手动创建了一个ts的后端koa项目，实现了ts编译，并且引入了关键的koa库。\n\n这一章我们来引入其他库，实现常见的post、get请求。\n\n## 二、实现监听\nkoa作为后端框架，可以实现对端口port的监听，所有通过该端口的请求，都会被监听到，那么koa的监听如何实现呢，这里一个简单的举例：\n```app.ts\nconst Koa = require('koa');\nconst app = new Koa();\n\napp.use(async ctx => {\n  ctx.body = 'Hello World';\n});\n\napp.listen(3000);\n```\n我们在app.ts中写入上面的代码，我们再来看一下package.json中的执行脚本：\n```package.json\n...\n\"scripts\": {\n    \"dev\": \"ts-node app.ts\",\n    \"build\": \"tsc\"\n  },\n...\n```\n从这里的脚本命令，我们知道，当我们在根目录的终端中执行npm命令：\n```terminal\nnpm run dev\n```\n时，ts-node就会去编译app.ts文件，当编译时，实例化了koa，并且listen了3000端口，那么这个时候，程序并不会直接退出exit，而是会处于pending状态，监听着来自端口3000的消息。\n\n上面的app.ts文件中，app.use方法是一个中间件写法，也就是说请求和响应都会经过这个中间件处理，而ctx.body被赋值'Hello World'这个字符串时，就表示任何经过3000端口的请求，都会收到'Hello World'这个字符串响应。\n\n## 三、引入router库，实现一个简易get请求\n在后端项目中，和前端的vue以及react都很类似，甚至在flutter中也有对应的路由概念router，哪怕在iOS的组件化之中，都是可以应用到router这样的概念。所以如果对这几个方向有过开发经验的同学，应该是可以理解router的概念的。\n\nrouter这个概念在后端中也很普及，golang的项目同样也是有应用到的，所以有时候经验积累的足够多的时候，很多原理都是相通的，与诸君共勉。\n\n我们讲正文吧，koa的router，其实就是请求的path，如何从端口监听到对应的path请求，并且对这个path请求做处理，也就是返回对应的接口响应。当你不使用router时，那么需要自己处理请求上下文中的path以及携带的请求参数。\n\n这里我使用的是\"@koa/router\"这个npm包处理koa的路由请求，大家可以在npm包网站：[https://www.npmjs.com/package/koa-router](https://www.npmjs.com/package/koa-router)查看这个package。\n\n我们在终端执行：\n```terminal\nnpm install @koa/router\n```\n并且安装对应的type支持包：\n```terminal\nnpm install --save-dev @types/koa__router\n```\n这样子，我们就可以做一下后端path路由，修改app.ts为：\n```app.ts\nvar Koa = require('koa');\nvar Router = require('koa-router');\n\nvar app = new Koa();\nvar router = new Router();\n\nrouter.get('/', (ctx, next) => {\n  // 处理类似http://127.0.0.1:3000的get请求\n  ctx.body = \"Hello World\";\n});\n\napp\n  .use(router.routes())\n  .use(router.allowedMethods());\n```\n\n正如这个代码注释中提到的，重新运行`npm run dev`时，在浏览器中输入`http://127.0.0.1:3000`，就可以在网页上显示字符串`Hello World`，那么一个简单的get请求就实现了。\n\n## 四、写一个post请求\n我们在上面的步骤中写了一个简单的router的get请求，这里我们发散一下思维，封装一个用户登录信息模块。\n\n在写登录信息模块之前，我们需要定义一下响应的类型结构，用来规范我们的响应数据格式。\n1. 定义响应码code的枚举：\n![error枚举](https://image.xinwei.ltd/image1731343743899.png)\n```error.ts\n/**\n * 接口返回的错误码\n */\nenum NetErrorCode {\n  NotLogin = 401,\n  ParamError = 403,\n  NotFound = 404,\n  Success = 200,\n}\n\nexport default NetErrorCode;\n```\n2. 定义响应返回格式：\n![reponse类](https://image.xinwei.ltd/image1731343834179.png)\n```response.ts\nimport NetErrorCode from \"./error\";\n\n/**\n * 网络请求的返回\n */\nexport default class NetResponse\u003CT> {\n  code: NetErrorCode;\n  msg?: string;\n  data?: T;\n\n  constructor(code: NetErrorCode, data: T, msg?: string) {\n    this.code = code;\n    this.data = data;\n    this.msg = msg;\n  }\n}\n```\n这里使用了泛型，可以返回对应类型的数据data.\n3. 创建一个router文件夹，用来存放对不同router的请求处理：\n- 登录router:\n![登录的router](https://image.xinwei.ltd/image1731344053980.png)\n```router.ts\nimport NetErrorCode from \"../dto/error\";\nimport NetResponse from \"../dto/response\";\n\nconst Router = require(\"@koa/router\");\n\nconst router = new Router();\n\nrouter.get(\"/\", (ctx: any, next: any) => {\n  console.log(\"请求了:\", ctx);\n  next();\n});\n\nrouter.post(\"/login\", (ctx: any, next: any) => {\n  console.log(\"登录信息是：\", ctx.request.body);\n  console.log(\"登录信息是--headers：\", ctx.request.headers);\n  ctx.body = new NetResponse\u003Cany>(NetErrorCode.Success, null, \"\");\n});\n\nexport default router;\n```\n- 用户router：\n![user router](https://image.xinwei.ltd/image1731344142227.png)\n```user.ts\nconst Router = require(\"@koa/router\");\n\nconst userRouter = new Router({\n  prefix: \"/user\",\n});\n\nuserRouter.get(\"/profile\", (ctx: any, next: any) => {\n  console.log(\"用户信息是--headers：\", typeof next);\n  ctx.body = ctx.request.body;\n});\n\nexport default userRouter;\n\n```\n这里解释一下，user router的实例化函数中，可以创建一个前缀，就像该例子中，我们定义了一个`/user`前缀，然后使用这个router实现一个get请求，那么这个user router就可以处理`http://127.0.0.1:3000/user/profile`这样的接口请求。\n4. 修改app.ts如下：\n```app.ts\nconst Koa = require(\"koa\");\n\nimport router from \"./src/router/router\";\nimport userRouter from \"./src/router/user\";\n\nconst app = new Koa();\n\n// 根请求、login请求\napp.use(router.routes()).use(router.allowedMethods());\n// 用户模块\napp.use(userRouter.routes()).use(userRouter.allowedMethods());\n\napp.listen(3000);\n\n```\n5. 本来到这一步，一切应该是可以正常接收get、post请求的，但。。。\n\n当你通过postman这个软件，模拟一个请求：`http://127.0.0.1:3000/login`\n![](https://image.xinwei.ltd/image1731344535982.png)\npostman的response中为空，vscode的终端输出结果是`undefined`，这是为何呢，原因是尽管router对koa的请求做了路由处理，但是没有对ctx做解析处理，所以我们从`ctx.request.body`中得到的是undefined.\n\n那么我们开始下一步。\n\n## 五、引入bodyparser库\n这个库就是用来做body解析的，当然还有其他的一些库，比如koa-body，这里我们使用bodyparser库，地址是：[https://www.npmjs.com/search?q=body-parser](https://www.npmjs.com/search?q=body-parser)\n\n执行终端命令：\n```terminal\n$ npm i @koa/bodyparser --save\n```\n\n修改app.ts为：\n```app.ts\nconst Koa = require(\"koa\");\nconst { bodyParser } = require(\"@koa/bodyparser\");\n\nimport router from \"./src/router/router\";\nimport userRouter from \"./src/router/user\";\n\nconst app = new Koa();\napp.use(bodyParser());\n\n// 根请求、login请求\napp.use(router.routes()).use(router.allowedMethods());\n// 用户模块\napp.use(userRouter.routes()).use(userRouter.allowedMethods());\n\napp.listen(3000);\n```\n如代码所示，我们引入bodyParser，并且以中间件的方式进行使用，那么在对端口3000发送的任何请求，都会同步解析到ctx.request之中，这样子就能获取post携带的参数。\n\n## 六、测试post携带参数请求\n![测试post请求](https://image.xinwei.ltd/image1731345214358.png)\n![终端输出](https://image.xinwei.ltd/image1731345246035.png)\n\n至此，post请求和get请求的案例就实现了。\n\n本章到此结束，下一章继续。\n","小型it项目koa后端开发记录，整理成册，希望对于想要学习或者参考的同学有帮助。","https://image.xinwei.ltd/image1731343743899.png",499668042977349,{"phone":15,"userId":13,"nickName":16,"vipType":17,"avatar":18,"sign":19,"createdAt":20},"13121171998","全栈老韩",1,"https://image.xinwei.ltd/images/IMG_5430.JPG","全栈工程师，擅长iOS App开发、前端（vue、react、nuxt、小程序&Taro）开发、Flutter、React Native、后端（midwayjs、golang、express、koa）开发、docker容器、seo优化等。","2024-01-01T16:14:30.305Z",2,{"id":21,"name":23},"IT技术",17,{"id":24,"name":26,"parentId":21},"Node",[],"",207,0,"koa get,koa post,get post,koa,node koa,koa后端,koa服务端开发,服务端开发,node开发,node服务端,node项目,koa项目"]