# koa2
**Repository Path**: josnfei/koa2
## Basic Information
- **Project Name**: koa2
- **Description**: koa2学习--前端码仔学习后端必走之路
- **Primary Language**: NodeJS
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2018-06-25
- **Last Updated**: 2023-09-05
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## koa2学习笔记
#### 搭建环境
- 安装Node.js
- 搭建环境
+ cd code //进入code文件夹
+ mkdir koa2 //创建koa2文件夹
+ cd koa2 //进入koa2文件夹
+ npm init -y
- 安装koa包
+ npm install --save koa
- 编写代码
+ 运行node index.js
#### async/await的使用方法
- 个人理解
+ async可以写异步函数 ,返回的是一个promise
+ await 是等这个异步执行后才会执行,并且必须放在async里面使用
```javascript
function takeLongTime(){
return new Promise(resolve=>{
setTimeout(()=>{
resolve('long_time_value')
},2000)
})
}
async function test(){
const v= await takeLongTime()
console.log(v); //返回的是promise
}
test();
```
#### 第03节:Get请求的接收
- 干嘛用的?
+ 可以获得前端发送过来的请求的参数
- 获得GET请求的方式有两种
+ 一种是从request中获得(格式两种)
+ ctx.request.query
+ ctx.request.querystring
+ 一种是一直从上下文中获得(格式两种)
+ ctx.query
+ ctx.querystring
- 获得的格式也有两种区别
+ query (返回的是对象形式)
+ {user:Dfei,age:18}
+ querystring (返回的是字符串形式)
+ user=Dfei&age=18
```javascript
// 第03节:Get请求的接收
const Koa=require('koa');
const App=new Koa();
App.use(async (ctx)=>{
console.log(ctx);
let url=ctx.url; //获取请求的地址 //返回 /?user=Dfei&age=18 形式
//从request中获取GET请求
let request=ctx.request;
let req_query=request.query; //返回GET请求的URL的参数,形式是对象 {user:Dfei,age:18}
let req_querystring=request.querystring //返回GET请求的URL的参数 形式是字符串 user=Dfei&age=18
// 从上下文中直接获取
let ctx_query=ctx.query; //{user:Dfei,age:18}
let ctx_querystring=ctx.querystring //user=Dfei&age=18
ctx.body={
url,
req_query,
req_querystring,
ctx_query,
ctx_querystring
}
})
// 浏览器访问 127.0.0.1:3000?user=Dfei&age=18
App.listen(3000,()=>{
console.log('服务器已启动')
})
/**
* 总结:获得GET请求的方式有两种,一种是从request中获得,一种是一直从上下文中获得。获得的格式也有两种:query和querystring。大家要区分记忆,并根据实际需求进行灵活变换。
*/
```
#### 第04,05节:POST请求如何接收(1,2)
- koa如何获取用户是什么请求?
+ ctx.method的方式,可以获取到是GET还是POST请求方式
- koa2如何处理POST 前端传过来的参数?
+ 原生方法,也就是不使用中间件的方法,看代码
```javascript
// 第05节:POST请求如何接收(2) 如何处理post前端传过来的参数
const Koa=require('koa');
const App=new Koa();
App.use(async (ctx)=>{
// GET请求
if(ctx.url=='/'&&ctx.method=='GET'){
let html=`
Koa2 request post demo
`;
ctx.body=html;
}else if(ctx.url=='/'&&ctx.method=='POST'){
// post请求处理
ctx.body=await parsePostData(ctx); //返回请求的参数?主要体现在这个函数里面
}else{
ctx.body='404未找到该页面'
}
})
// 处理前端post传过来的参数
function parsePostData(ctx){
return new Promise((resolve,reject)=>{
try{
let postdata='';
ctx.req.on('data',(data)=>{ //在这里监听 拿post的参数拼接起来
postdata+=data
})
// console.log(postdata,'拼接')
ctx.req.addListener('end',function(){ //监听完成
let parseData=parseQueryStr(postdata)
// console.log(parseData,'完成')
resolve(parseData)
})
}catch(error){
reject(error)
}
})
}
// url参数获取函数,返回的是组装好的对象
// userName=acb&age=12&webSite=hello+world 处理成 { userName: 'acb', age: '12', webSite: 'hello+world' }
function parseQueryStr(queryStr){
// console.log(queryStr)
let queryData={};
let queryStrList = queryStr.split('&');
// console.log(queryStrList);
for( let [index,queryStr] of queryStrList.entries() ){
let itemList = queryStr.split('=');
// console.log(itemList);
queryData[itemList[0]] = decodeURIComponent(itemList[1]);
}
return queryData
}
App.listen(3000,()=>{
console.log('post请求的服务器已经启动')
})
```
#### 第06节:koa-bodyparser中间件
- 干嘛用的???
+ 快速获取前端POST请求传递过来的参数
- 使用步骤
+ 1. 下载包 `npm i --save koa-bodyparser`
+ 2. 引入包 `const bodyParser=require(koa-bodyparser)`
+ 3. 使用1 `App.use(bodyParser())`
+ 4. 使用2 `ctx.request.body` 中可以获取post发送过来的参数
- 注意点
+ 不管是否是fromData的方式的post请求,还是类似正常的AJAX的post,都可以通过这个拿到请求的参数
- 补充1个知识,就是解决跨域问题需要的中间件
+ 安装 `npm install --save koa2-cors` 中间件
+ 使用 `App.use(cors())`
```javascript
// 第06节:koa-bodyparser中间件
// 作用: 对于POST请求的处理,koa-bodyparser中间件可以把koa2上下文的formData数据解析到ctx.request.body中。
// 注意,这里说的是formData ,也就是说表单的形式,传过来的是age=12&name=Dfei 这种形式,其他形式用哪个中间件,暂时未知(已得到答案,一样用这个,jq的方法测试过,没毛病)
const Koa = require('koa');
const App = new Koa();
const bodyParser = require('koa-bodyparser'); //处理类似表单formData的方式传递过来的参数的中间件 npm install --save koa-bodyparser@3
// 直接可以用ctx.request.body进行获取POST请求参数
// 另外加n 支持跨域请求 npm install --save koa2-cors
const cors=require('koa2-cors')
// 允许跨域
App.use(cors())
App.use(bodyParser());
App.use(async(ctx)=>{
if(ctx.url==='/' && ctx.method==='GET'){
//显示表单页面
let html=`
JSPang Koa2 request POST
`;
ctx.body=html;
}else if(ctx.url==='/' && ctx.method==='POST'){
let postData= ctx.request.body;
ctx.body=postData;
}else{
ctx.body='404!
';
}
});
App.listen(3000,()=>{
console.log('服务已启动,端口号3000');
});
// 总结(必看)
// post获取穿过来的参数
// 利用koa-bodyparser可以获得post传过来的参数,是对象的形式
// 通过ctx.request.body获取
// get 获取传过来的参数通过
/**
*
* 从request中获取GET请求
let request=ctx.request;
let req_query=request.query; //返回GET请求的URL的参数,形式是对象 {user:Dfei,age:18}
let req_querystring=request.querystring //返回GET请求的URL的参数 形式是字符串 user=Dfei&age=18
// 从上下文中直接获取
let ctx_query=ctx.query; //{user:Dfei,age:18}
let ctx_querystring=ctx.querystring //user=Dfei&age=18
*/
```
#### 第08节:Koa-router中间件(1)入门
- 干嘛用的???
+ 用来接收前端请求的路径,和之前常用的 `App.use( async(ctx)=>{ if(ctx.url=='/') } )` 方式是一样的,只是这个中间件用的更方便,功能多
- 使用步骤
+ 1. 安装 `npm i --save koa-router`
+ 2. 实例化 `const router=new Router();`
+ 3. 使用 `router.get('/',function(ctx,next){}).get('/index',()=>{})` 有多个则继续写下去,Post请求也是继续往后写
+ 4. 加载中间件 `App.use(router.routes())
.use(router.allowedMethods());` 这个是必写的
```javascript
// 第08节:Koa-router中间件(1)入门
var Koa=require('koa');
var Router=require('koa-router'); //路由
var App=new Koa();
const router=new Router();
// 基础案例
router.get('/',function(ctx,next){
ctx.body="Hello Dfei"
}) // 多页面配置 其实多页面的添加只要继续在下面填写get或者Post就可以了,比如我们再加一个todo的页面
.get('/todo',function(ctx,next){
ctx.body='Hello zhouwenfei'
})
App.use(router.routes())
.use(router.allowedMethods());
App.listen(3000,function(){
console.log('服务器已启动')
})
// 总结:
// 总结:我们可以发现有了中间件进行配置路由非常简单,但是路由还是很复杂的,今天讲的只是koa-router最基本的用法,我们会在下面几节课中不断增加难度。
```
#### 第09节:Koa-router中间件(2)层级
- 层级是什么意思?
+ 设置前缀
+ 比如: 有时候我们想把所有的路径前面都再加入一个级别,比如原来我们访问的路径是http://127.0.0.1:3000/todo,现在我们希望在所有的路径前面都加上一个jspang层级,把路径变成http://127.0.0.1:3000/jspang/todo.这时候就可以使用层级来完成这个功能。路由在创建的时候是可以指定一个前缀的,这个前缀会被至于路由的最顶层,也就是说,这个路由的所有请求都是相对于这个前缀的
- 其他看代码吧,语言无法表达
```javascript
// 第09节:Koa-router中间件(2)层级
const Koa=require('koa');
const Router=require('koa-router');
const App=new Koa()
const router=new Router({
prefix:'/Dfei' //设置前缀
});
// 设置前缀说明
/**
* 有时候我们想把所有的路径前面都再加入一个级别,比如原来我们访问的路径是http://127.0.0.1:3000/todo,现在我们希望在所有的路径前面都加上一个jspang层级,把路径变成http://127.0.0.1:3000/jspang/todo.这时候就可以使用层级来完成这个功能。路由在创建的时候是可以指定一个前缀的,这个前缀会被至于路由的最顶层,也就是说,这个路由的所有请求都是相对于这个前缀的。
*/
router.get('/dfei',(ctx,next)=>{
ctx.body='DFEI'
})
// 需求
/**
* 设置前缀一般都是全局的,并不能实现路由的层级,如果你想为单个页面设置层级,也是很简单的。只要在use时使用路径就可以了。
例如这种写法装载路由层级,这里的router相当于父级:router.use(‘/page’, page.routes(), page.allowedMethods())。
通过这种写法的好处是并不是全局的,我们可以给不同的路由加层级。
代码如下:我们声明了两个路由,第一个是home,第二个是page.然后通过use赋予不同的前层级。
* */
// 两个子路由
const home=new Router()
home.get('/dfei',(ctx,next)=>{
ctx.body='Home dfei'
})
.get('/todo',(ctx,next)=>{
ctx.body='Home todo'
})
const page=new Router();
page.get('/dfei',(ctx,next)=>{
ctx.body='page dfei'
})
.get('/todo',(ctx,next)=>{
ctx.body='page todo'
})
// 转载所有子路由
const routers=new Router();
routers.use('/home',home.routes(),home.allowedMethods()); //浏览器访问: 127.0.0.1:3000/home/dfei 127.0.0.1:3000/home/todo
routers.use('/page',page.routes(),page.allowedMethods()); //浏览器访问: 127.0.0.1:3000/page/dfei 127.0.0.1:3000/page/todo
// 加载路由中间件
App.use(router.routes()).use(router.allowedMethods()); //全局的路由中间件
// 加载路由中间件
App.use(routers.routes()).use(routers.allowedMethods()); //刚才分开的路由中间件
App.listen(3000,()=>{
console.log('服务已启动')
})
```
#### 第10节:Koa-router中间件(3)参数(总结)
- 实际是前几节的内容,当总结了
- 前端GET请求发送过来的参数如何获取 (两种方法,每种方法又有两种模式,可看第三节)
- 前端POST请求发送过来的参数如何获取(`koa-bodyparser中间件`)
- `koa-router`中间件的时候,别忘了最后需要加载路由中间件,也就是`App.use(router.routes())
.use(router.allowedMethods());`
```javascript
// 第10节:Koa-router中间件(3)参数
const Koa=require('koa');
const Router=require('koa-router'); //路由中间件
const bodyParser=require('koa-bodyparser'); //post请求获取前端传过来的参数 使用 ctx.request.body
const App=new Koa();
const router=new Router();
App.use(bodyParser()) ; //使用koa-bodyparsr 中间件
router.get('/dfei',(ctx,next)=>{ //浏览器访问:http://localhost:3000/dfei?name=wenfei&age=19 即可监听到这个/dfei请求
console.log(ctx.query,'get传后台的参数'); //获取get请求的传递过来的恩参数
console.log(ctx.url); //如果http://localhost:3000/dfei?name=wenfei&age=19 得到 /dfei?name=wenfei&age=19 如果 如果http://localhost:3000/dfei 得到 /dfei
let html=`
Koa2 request post demo
`;
ctx.body=html
})
.post('/post',(ctx,next)=>{
console.log(ctx.request.body,'前端post传过来的参数')
ctx.body=ctx.request.body;
})
// 加载路由中间件
App.use(router.routes())
.use(router.allowedMethods());
App.listen(3000,()=>{
console.log('服务启动成功')
})
```
#### 第11节:Koa2中使用cookie
- 干嘛用的?
+ 保存cookie
- 方法
+ 获取
+ `ctx.cookies.get(name,[optins])`:读取上下文请求中的cookie。
+ 设置
+ `ctx.cookies.set(name,value,[options])`:在上下文中写入cookie。
- 注意点
+ 设置时候的options里面的path的设置是否必须,看代码注释
```javascript
// 第11节:Koa2中使用cookie
/**
*开发中制作登录和保存用户信息在本地,最常用的就是cookie操作。比如我们在作一个登录功能时,希望用户在接下来的一周内都不需要重新登录就可以访问资源,这时候就需要我们操作cookie来完成我们的需求。koa的上下文(ctx)直接提供了读取和写入的方法。
*
*/
/** cookie方法使用
*
* 获取:
* ctx.cookies.get(name,[optins]):读取上下文请求中的cookie。
*
* 设置:
* ctx.cookies.set(name,value,[options]):在上下文中写入cookie。
*
* */
const Koa=require('koa');
const App=new Koa();
App.use(async (ctx)=>{
if(ctx.url=='/index'){
ctx.cookies.set(
'myName','Dfei',{
domain:'localhost', //写COOKIE所在的域名 就算你是在Localhost这个域名下,我也不会生成这个cookie
path:'/index', //写cookie所在的路径 如果访问的是localhost:3000/aa,则读取不到cookie,访问localhost:3000/index/aa,就可以拿到。 这就是这个path路径搞的鬼, 这里注意一下,如果需要全局,path配/就可以了
maxAge:1000*60*60*24*365, //cookie有效期
expires:new Date('2019-12-1'), //cookie失效时间
httpOnly:false, //是否只用于http请求
overwrite:false, //是否允许重写
}
)
ctx.body=ctx.cookies.get('myName')+'cookie 已 OK'
}else{
if(ctx.cookies.get('myName')){
ctx.body=ctx.cookies.get('myName')
}else{
ctx.body='cookie is no'
}
}
})
App.listen(3000,()=>{
console.log('服务启动成功')
})
```
#### 第12节:Koa2的模板初识(ejs)
- 干嘛用的???
+ 返回前端html代码解析的模板引擎,类似art-template
- 使用步骤(需要安装两个东西)
+ 1. 安装中间件 `cnpm install --save koa-views` 注意的是是koa-views 而不是koa-view
+ 引入:` const view=require('koa-views');` //在koa2中使用模板机制必须依靠中间件
+ 使用:`App.use(view(path.join(__dirname,'./view'),{
extension:'ejs' //告诉她,我用的是哪个模板引擎
}))`
+ 2. 安装模板引擎 `npm install --save ejs`
```javascript
// 第12节:Koa2的模板初识(ejs)
/**
* 安装中间件 (在koa2中使用模板机制必须依靠中间件,我们这里选择koa-views中间件,先使用npm来进行安装。)
* cnpm install --save koa-views (注意的是是koa-views 而不是koa-view)
*
*
* 安装ejs模板引擎 (ejs是个著名并强大的模板引擎,可以单独安装。很多开源软件都采用了ejs模板引擎。)
*
* npm install --save ejs
* */
const Koa=require('koa');
const view=require('koa-views'); //在koa2中使用模板机制必须依靠中间件
const path=require('path'); //node里面的api,处理文件路径
const App=new Koa();
App.use(view(path.join(__dirname,'./view'),{
extension:'ejs' //告诉她,我用的是哪个模板引擎
}))
App.use(async (ctx)=>{
let title='Dfei';
await ctx.render('index',{ //渲染
title
})
})
App.listen(3000,()=>{
console.log('服务已启动')
})
```
#### 第13节:koa-static静态资源中间件
- 干嘛用的???
+ 服务器返回给前端的静态资源。
+ 比如,返回服务器IP加图片地址,可以访问到该图片
- 使用步骤
+ 安装 `npm install --save koa-static`
+ 引入 ` const static=require('koa-static');` 静态资源中间件
+ 使用,看代码
```javascript
// 第13节:koa-static静态资源中间件
/**
* 在后台开发中不仅有需要代码处理的业务逻辑请求,也会有很多的静态资源请求。比如请求js,css,jpg,png这些静态资源请求。也非常的多,有些时候还会访问静态资源路径。用koa2自己些这些静态资源访问是完全可以的,但是代码会雍长一些。所以这节课我们利用koa-static中间件来实现静态资源的访问。
*/
/**
* 安装koa-static:
* npm install --save koa-static
*
* 新建static文件夹
*
*/
const Koa=require('koa');
const path=require('path');
const static=require('koa-static'); //静态资源中间件
const App=new Koa();
const staticPath='./static'
App.use(static(
path.join(__dirname, staticPath)
)
); //使用静态资源中间件
App.use(async (ctx)=>{
ctx.body='Hello world';
})
//浏览器访问 127.0.0.1:3000/appShow.jpg 就可以访问到静态资源了
App.listen(3000,()=>{
console.log('启动成功')
})
```