# koa-note **Repository Path**: topazur/koa-note ## Basic Information - **Project Name**: koa-note - **Description**: 来源于廖雪峰博客及B站视屏-收获的学习笔记 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-05-18 - **Last Updated**: 2020-12-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Koa (koajs) -- 基于 Node.js 平台的下一代 web 开发框架 | Koajs 中文文档 > 与Express差不多(没有配置内置路由),但是避免了异步的嵌套。阿里在koa的基础上封装了egg # 安装 ## Node.js版本必须高于V7.6,因为在V7.6才完全支持async/await语法; 要在 node < 7.6 版本的 Koa 中使用 async 方法, 我们推荐使用 Babel 实现 Async 方法,使用 [babel's require hook](https://www.babeljs.cn/docs/babel-register). ## 安装没有脚手架 npm init -y npm install koa --save ### 启动脚本 `node --debug-brk=40645 --nolazy app.js` - 调试?? `node app.js` - 执行js文件 `npm start` - 脚本 ```bash "dependencies": { "koa": "^2.12.0", "koa-bodyparser": "^4.3.0", "koa-router": "^8.0.8", "mime": "^2.4.5", "mz": "^2.7.0", "nunjucks": "^3.2.1" } ``` ### app.js ```js // express写法 app.use(function(req,res) { // more res.send('express的嵌套写法') }) // koa写法 app.use(async (ctx, next) => { await next(); ctx.response.body = "koa的async/await写法" }) ``` #### 设置 1. 级联的概念: 其实如果路由返回之后不往下走了是不用写next的; next的表示只在此做一层逻辑,然后继续往下走 2. 我们知道Koa是一个构造函数,那么我们需要关注以下几点 ```js // 一、Koa实例app上的属性: /* 1. app.env `默认是 NODE_ENV 或 "development"` 2. app.keys `签名的 cookie 密钥数组` 3. app.proxy `当真正的代理头字段将被信任时` 4. `忽略 .subdomains 的 app.subdomainOffset 偏移量,默认为 2` 5. app.proxyIpHeader `代理 ip 消息头, 默认为 X-Forwarded-For` 6. app.maxIpsCount `从代理 ip 消息头读取的最大 ips, 默认为 0 (代表无限)` */ 方式一: 通过参数传递给构造函数 const app = new Koa({ proxy: true }); 方式二: 动态的设置 app.proxy = true; // 二、Koa实例app上的方法: app.listen(3000, cb); app.callback() app.use(function) app.keys=[] //设置签名的 Cookie 密钥 app.context //app.context 是从其创建 ctx 的原型,添加全局使用的属性,如: 设置app.context.db = db();=>就可以通过ctx.db访问 // 错误处理 app.on('error', (err, ctx) => { // Koa 将用一个 500 “内部服务器错误” 进行适当的响应,进行客户端的优化处理 console.error('server error', err) }); // 上下文 app.use(async ctx => { ctx; // 这是 Context ctx.request; // 这是 koa Request ctx.response; // 这是 koa Response // ctx.type 和 ctx.length 委托给 response 对象,ctx.path 和 ctx.method 委托给 request ctx.req; || ctx.request; //Node 的 request 对象. ctx.res; || ctx.response; //Node 的 response 对象. /* 绕过 Koa 的 response 处理是 不被支持的. 应避免使用以下 node 属性 res.statusCode res.writeHead() res.write() res.end()*/ ctx.state; //命名空间 ctx.app; //应用程序实例引用 ctx.app.emit; //扩展的内部的EventEmitter ctx.cookies.get(name, [options]);ctx.cookies.set(name, value, [options]); ctx.throw([status], [msg], [properties]); //抛出一个包含 .status 属性错误的帮助方法,其默认值为 500(原理: koa 使用 http-errors 来创建错误) ctx.assert(value, [status], [msg], [properties]); //当 !value 时抛出一个类似 .throw 错误的帮助方法(原理: koa 使用 http-assert 作为断言) ctx.respond; //为了绕过 Koa 的内置 response 处理,想要写入原始的 res 对象而不是让 Koa 处理你的 response.(Koa 中使用传统的 fn(req, res) 功能和中间件的人,而不建议在koa的async中使用,否则被认为是一个 hack) }); ``` 3. request Request 别名 | | | | 以下访问器和 Request.xxx 别名等效 :-: | :-: | :-: | :-: | :-: ctx.header | ctx.headers | ctx.method | ctx.method= | **ctx.socket**| ctx.url | ctx.url=| ctx.originalUrl | ctx.origin | ctx.href| ctx.path | ctx.path=| ctx.query | ctx.query= | ctx.querystring| ctx.querystring= | ctx.host| ctx.hostname | ctx.fresh | ctx.stale| ctx.protocol | ctx.secure| ctx.ip | ctx.ips | ctx.subdomains| ctx.is() | ctx.accepts()| ctx.acceptsEncodings() | ctx.acceptsCharsets() |空 | ctx.acceptsLanguages() | ctx.get()| 空|空 | 空| 4. response Response 别名 | | | | 以下访问器和 Response.xxx 别名等效 :-: | :-: | :-: | :-: | :-: **ctx..status&ctx.message**| ctx.length| **ctx.body** | | | ctx.get(field)不区分大小写 | ctx.has(field)| ctx.set(field, value) | ctx.append(field, value) | ctx.set(fields)| ctx.remove(field) | ctx.type| ctx.redirect(url, [alt]) | ctx.attachment([filename], [options]) | ctx.headerSent| ctx.lastModified | ctx.etag| ctx.vary(field) | ctx.flushHeaders() | ...| 3.2 get传值 如何获取参数? 方式一:(推荐) ctx.query //打印{aid: '123'} 获取的是对象(用的最多的方式) ctx.querystring // aid=123&name=zhangsan 获取的是一个字符串 方式二:我们可以从ctx里面的request里面获取get传值 ctx.request.requery // {aid: '123'} ctx.quest.querystring // aid=123&name=zhangsan 3.3 动态路由 router.get('/newscontent/:aid', async (ctx) => { console.log(ctx.params) // { aid : '123'} ctx.body = '新闻详情' }) 动态路由可以传入多个值 router.get('/newscontent/:aid/:cid', async (ctx) => { console.log(ctx.params) //{aid:'123' , cid: '456'} ctx.body = '新闻详情' }) 3.3 post应用插件之后: ctx.request.body ### 中间件 koa middleware 如果get、post回调函数中没有next参数,name就匹配上第一个路由,就不会往下匹配了,如果想往下匹配,那么就需要写next() 4.1 中间件使用 中间件的功能:执行任何代码、修改请求和响应对象、 终结请求--响应循环、调用堆栈中的下一个中间件 4.2 应用级中间件 定义:就是在匹配所有路由之前进行操作某种需求 第一个参数没有,或者是共有的''和'/' => 当前路由匹配完成以后继续向下匹配,不写就不会向下匹配 4.3 路由中间件 定义: 匹配特定路由前进行某种操作 4.4 错误处理中间件 express的中间件和路由有前后顺序,而koa没有顺序,即使放在路由最后面,也先执行中间件 4.5 执行原理: koa就像洋葱一样,先执行request,匹配到之后,然后再反向执行response(从外到内,再从内到外) 让我们再仔细看看koa的执行逻辑。核心代码是: ```js app.use(async (ctx, next) => { await next(); ctx.response.type = 'text/html'; ctx.response.body = '