koa学习笔记

一.koa框架介绍

Node.js 是一个异步的世界,官方 API 支持的都是 callback 形式的异步编程模型,这 会带来许多问题,例如:1、callback 嵌套问题 2、异步函数中可能同步调用 callback 返回 数据,带来不一致性。为了解决以上问题 Koa 出现了。

Koa – 基于 Node.js 平台的下一代 web 开发框架

koa 是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提 升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的 函数库,使得编写 Web 应用变得得心应手。开发思路和 express 差不多,最大的特点就是 可以避免异步嵌套。

安装koa

npm install --save koa / cnpm install --save koa

–save 参数,表示自动修改 package.json 文件,自动添加依赖项。

简单使用:

var koa =require('koa');
var app=new koa();  //实例化

//配置路由

//中间件

//express写法
//app.use(function(req,res){
//
//    res.send('返回数据')
//})


app.use( async (ctx)=>{
     ctx.body='你好 koa2.x';
})

app.listen(3000);  //监听3000端口

二.Koa异步处理Async、Await和Promise的使用

async 是“异步”的简写,而 await 可以认为是 async wait 的简写。所以应该很好理解 async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。

简单理解:

async 是让方法变成异步。

await 是等待异步方法执行完成。

详细说明:

async 是让方法变成异步,在终端里用 node 执行这段代码,你会发现输出了 Promise {‘Hello async’ },这时候会发现它返回的是 Promise。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-npYkLq39-1598271285099)(https://i.loli.net/2020/08/22/vWajMAkbwT4IV97.png)]

await 在等待 async 方法执行完毕,其实 await 等待的只是一个表达式,这个表达式在官方文档里说的是 Promise 对象,但是它也可以接受普通值。 **注意:**await 必须在 async 方法中 才可以使用因为 await 访问本身就会造成程序停止堵塞,所以必须在异步方法中才可以使用。

//async 是让方法变成异步
/*
普通方法
 function getData(){

 return '这是一个数据';
 }

 console.log(getData());  //这是一个数据
* */



/*
async 是让方法变成异步
 async function getData(){

 return '这是一个数据';
 }

 console.log(getData());  //Promise { '这是一个数据' }


* */



/*如何获取async 异步方法里面的数据的第一种方法
 async function getData(){

     return '这是一个数据';
 }

 var p=getData();
 p.then((data)=>{
     console.log(data);
 })

* */


//await 是等待异步方法执行完成,可以获取异步方法里面的数据,但是必须得用在异步方法里面

/*await 错误的用法
 async function getData(){

    return '这是一个数据';
 }

 var d=await getData();
 console.log(d);  //await is only valid in async function

* */


//await 是等待异步方法执行完成,可以获取异步方法里面的数据,但是必须得用在异步方法里面

/*
 async function getData(){

    return '这是一个数据';
 }

 async function test(){

    var d=await getData();

    console.log(d);
 }
 test();

* */


//await 阻塞的功能 ,把异步改成一个同步


//async function getData(){
//    console.log(2);
//    return '这是一个数据';
//}
//async function test(){
//
//    console.log(1);
//    var d=await getData();
//    console.log(d);
//    console.log(3);
//}
//test();  //1  2  3





//async 定义的方法返回的是 Promise对象。



/*
 function getData(){

    return new Promise((resolve,reject)=>{
          setTimeout(()=>{
                 var username='张三';
                 resolve(username);


          },1000)
     })
 }

 var p=getData();
 p.then(function(d){      //异步的方式获取
        console.log(d);

 })

* */
//async/await 同时使用 async 会将其后的函数(函数表达式或 Lambda)的返回值封装成一个 Promise 对象,而 await 会等待这个 Promise 完成,并将其 resolve 的结果返回出来。

function getData(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            var username='张三';
            resolve(username);

        },1000)
    })
}
async function test(){

    var data=await getData();
    console.log(data);
}

test();

三.koa路由

路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET、POST 等) 组成的,涉及到应用如何响应客户端对某个网站节点的访问。

通俗的讲:路由就是根据不同的 URL 地址,加载不同的页面实现不同的功能

安裝koa-router

npm install --save koa-router

//引入 koa模块

var Koa=require('koa');

var Router = require('@koa/router');

//实例化
var app=new Koa();

var router = new Router();


//ctx  上下文 context ,包含了request 和response等信息

//配置路由
router.get('/',async (ctx)=>{

    ctx.body='首页'; /*返回数据    相当于:原生里面的res.writeHead()     res.end()*/
}).get('/news',async (ctx)=>{

    ctx.body="这是一个新闻页面"
})
//启动路由

app
    .use(router.routes())   /*启动路由*/
    .use(router.allowedMethods());   /*可以配置也可以不配置,建议配置,*/


/*
 router.allowedMethods()作用: 这是官方文档的推荐用法,我们可以
 看到 router.allowedMethods()用在了路由匹配 router.routes()之后,所以在当所有
 路由中间件最后调用.此时根据 ctx.status 设置 response 响应头
*/

app.listen(3000);

四.Koa路由获取get传值

//引入 koa模块

var Koa=require('koa');

var router = require('@koa/router')();  /*引入是实例化路由** 推荐*/

//实例化
var app=new Koa();

router.get('/',async (ctx)=>{
    ctx.body="首页";

})

router.get('/news',async (ctx)=>{
    ctx.body="新闻列表页面";

})
//获取get传值
//http://localhost:3002/newscontent?aid=123

router.get('/newscontent',async (ctx)=>{

    /*在 koa2 中 GET 传值通过 request 接收,但是接收的方法有两种:query 和 querystring。
     query:返回的是格式化好的参数对象。
     querystring:返回的是请求字符串。*/

    //从ctx中读取get传值

    console.log(ctx.query);  //{ aid: '123' }       获取的是对象   用的最多的方式      ******推荐

    console.log(ctx.querystring);  //aid=123&name=zhangsan      获取的是一个字符串

    console.log(ctx.url);   //获取url地址

    //ctx里面的request里面获取get传值

    console.log(ctx.request.url);
    console.log(ctx.request.query);   //{ aid: '123', name: 'zhangsan' }  对象
    console.log(ctx.request.querystring);   //aid=123&name=zhangsan


    ctx.body="新闻详情";

})


app.use(router.routes());   /*启动路由*/
app.use(router.allowedMethods());
/*
*  router.allowedMethods()作用: 这是官方文档的推荐用法,我们可以
 看到 router.allowedMethods()用在了路由匹配 router.routes()之后,所以在当所有
 路由中间件最后调用.此时根据 ctx.status 设置 response 响应头*/
app.listen(3002);

五.koa中间件

1.什么是Koa的中间件

**通俗的讲:**中间件就是匹配路由之前或者匹配路由完成做的一系列的操作,我们就可以

把它叫做中间件。

express **中间件(Middleware)是一个函数,它可以访问请求对象(request object (req)), 响应对象(response object (res)), 和 web 应用中处理请求-响应循环流程中的中间件,一 般被命名为 next 的变量。在 Koa 中中间件和 express 有点类似。

中间件的功能包括:

执行任何代码。

修改请求和响应对象。

终结请求-响应循环。

调用堆栈中的下一个中间件。

如果我的 get、post 回调函数中,没有 next 参数,那么就匹配上第一个路由,就不会往下匹 配了。如果想往下匹配的话,那么需要写 next()

2.Koa 应用可使用如下几种中间件:

应用级中间件:

//引入 koa模块

var Koa=require('koa');
var router = require('koa-router')();  /*引入是实例化路由** 推荐*/
var app=new Koa();

//Koa中间件

//匹配任何路由  ,如果不写next,这个路由被匹配到了就不会继续向下匹配
/*
 app.use(async (ctx)=>{
    ctx.body='这是一个中间件';
 })
* */

/*匹配路由之前打印日期*/
app.use(async (ctx,next)=>{

     console.log(new Date())

    await next(); /*当前路由匹配完成以后继续向下匹配*/
})

router.get('/',async (ctx)=>{

    ctx.body="首页";

})
router.get('/news',async (ctx)=>{
    ctx.body="新闻列表页面";

})
router.get('/login',async (ctx)=>{
    ctx.body="新闻列表页面";
})


app.use(router.routes());   /*启动路由*/
app.use(router.allowedMethods());
app.listen(3002);

路由级中间件:


//引入 koa模块

var Koa=require('koa');
var router = require('koa-router')();  /*引入是实例化路由** 推荐*/
var app=new Koa();

//Koa中间件

//匹配任何路由  ,如果不写next,这个路由被匹配到了就不会继续向下匹配


router.get('/',async (ctx)=>{

    ctx.body="首页";

})
// 匹配到news路由以后继续向下匹配路由
router.get('/news',async (ctx,next)=>{
    console.log('这是一个新闻1');

     await next();
})
router.get('/news',async (ctx)=>{

    ctx.body='新闻2';
})

router.get('/login',async (ctx)=>{
    ctx.body="新闻列表页面";
})


app.use(router.routes());   /*启动路由*/
app.use(router.allowedMethods());
app.listen(3002);








错误处理中间件


//引入 koa模块

var Koa=require('koa');
var router = require('koa-router')();  /*引入是实例化路由** 推荐*/
var app=new Koa();

//Koa中间件

//匹配任何路由  ,如果不写next,这个路由被匹配到了就不会继续向下匹配

//www.域名.com/news
app.use(async (ctx,next)=>{
    console.log('这是一个中间件01');
    next();

    if(ctx.status==404){   /*如果页面找不到*/
        ctx.status = 404;
        ctx.body="这是一个 404 页面"
    }else{
        console.log(ctx.url);
    }
})

router.get('/',async (ctx)=>{

    ctx.body="首页";

})
router.get('/news',async (ctx)=>{
    console.log('这是新闻2');
    ctx.body='这是一个新闻';
})
router.get('/login',async (ctx)=>{
    ctx.body="新闻列表页面";
})



app.use(router.routes());   /*启动路由*/
app.use(router.allowedMethods());
app.listen(3002);








第三方中间件

const static = require('koa-static'); 
	const staticPath = './static'; 
	app.use(static(
	path.join( __dirname, staticPath)
)) 

const bodyParser = require('koa-bodyparser');
app.use(bodyParser());

3.koa中间件处理流程


QQ截图20200822222246.png

//Koa 选择了洋葱圈模型

//引入 koa模块

var Koa=require('koa');
var router = require('koa-router')();  /*引入是实例化路由** 推荐*/
var app=new Koa();

//Koa中间件

//匹配任何路由  ,如果不写next,这个路由被匹配到了就不会继续向下匹配

//www.域名.com/news
app.use(async (ctx,next)=>{
    console.log('1、这是第一个中间件01');
    await next();

    console.log('5、匹配路由完成以后又会返回来执行中间件');

})

app.use(async (ctx,next)=>{
    console.log('2、这是第二个中间件02');
    await next();

    console.log('4、匹配路由完成以后又会返回来执行中间件');

})

router.get('/',async (ctx)=>{

    ctx.body="首页";

})
router.get('/news',async (ctx)=>{

    console.log('3、匹配到了news这个路由');
    ctx.body='这是一个新闻';

})


app.use(router.routes());   /*启动路由*/
app.use(router.allowedMethods());
app.listen(3002);
1、这是第一个中间件
2、这是第二个中间件
3、匹配到news路由
4、匹配路由完成以后返回来执行中间件
5、匹配路由完成以后返回来执行中间件

await next();

console.log('5、匹配路由完成以后又会返回来执行中间件');

})

app.use(async (ctx,next)=>{
console.log(‘2、这是第二个中间件02’);
await next();

console.log('4、匹配路由完成以后又会返回来执行中间件');

})

router.get(’/’,async (ctx)=>{

ctx.body="首页";

})
router.get(’/news’,async (ctx)=>{

console.log('3、匹配到了news这个路由');
ctx.body='这是一个新闻';

})

app.use(router.routes()); /启动路由/
app.use(router.allowedMethods());
app.listen(3002);


1、这是第一个中间件
2、这是第二个中间件
3、匹配到news路由
4、匹配路由完成以后返回来执行中间件
5、匹配路由完成以后返回来执行中间件



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值