安装koa
npm i koa
架设 HTTP 服务
const Koa = require('koa');
const app = new Koa();
app.listen(3000);
## koa中的异步
Context 对象
Koa 提供一个 Context 对象,表示一次对话的上下文(可以理解为上(request)下(response)沟通的环境)。
通过加工这个对象,就可以控制返回给用户的内容。
const Koa = require('koa');//引进koa
const app = new Koa(); //构建一个实例
const main = ctx => {
ctx.response.body = 'Hello World'; // ctx.response
};
app.use(main);
app.listen(3000);
***为了便于访问和调用,许多 context 的属性和方法,代理了 ctx.request 和 ctx.response 所对应的等价方法, 比如说 ctx.type 和 ctx.length 代理了 response 对象中对应的方法,ctx.path 和 ctx.method 代理了 request 对象中对应的方法。
- ctx.request; // koa的request对象,包装后的nodejs的request对象
- ctx.response; // 这是 koa Response
- ctrx.req // nodejs的response对象
- ctx.res // nodejs的request对象
- ctx.app 应用程序实例引用
更多ctx的api请查找官网
koa的执行顺序和异步
1.koa通过next()方法调用下一个中间件。
let Koa = require('koa');
// app 是监听函数
let app = new Koa();
// koa里面 就两个常用的方法 listen use
app.use(function(ctx,next){
ctx.body = {'name':'zfpx'}
throw new Error('出错了');//注释掉就会执行next(),访问3000得到name:xiaoming,没有注释就会被错误捕获。
next();
});
app.use(function(ctx,next){
ctx.body = {'name':'xiaoming'}
});
// 监听错误捕获
app.on('error',function(err){
console.log(err);
});
// 调用next就会执行下一个中间件,ctx.body 可以设置多次,以最后的为主,等待中间件全部执行完 会将ctx.body结果响应给客户端
app.listen(3000);
看下面代码 写出执行顺序
let Koa = require('Koa');
let app = new Koa();
app.use((ctx,next)=>{
console.log(1);
return next(); // 我们在这调用next方法
console.log(2)
});
app.use((ctx,next)=>{
console.log(3);
next();
console.log(4)
})
app.listen(3000);
答案是1-3-4 上面的执行代码等同于下面的。是不是一目了然了。return后面的语句不执行所以2没有打印
app.use((ctx,next)=>{
console.log(1);
return app.use((ctx,next)=>{
console.log(3);
next();
console.log(4)
}); // 我们在这调用next方法
console.log(2)
});
2.koa的异步 有的时候我们需要一个中间件需要在另外一个异步函数执行完返回结果后执行。这个时候我们就需要异步koa了。 在koa中会把异步的方法全部封装成promise
app.use((ctx,next)=>{
console.log(3);
setTimeout(()=>{
console.log(4)
},3000)
console.log(5) //这个代码并不会等待定时器执行完在执行。
next()
})
// 3-5-4
我们想要的效果是3-4-5。这个时候就需要异步了。
在koa中
// 支持异步操作
// 在koa中会把异步的方法全部封装成promise
function log(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('log');
resolve();
},3000)
})
}
//先执行第一个中间件函数 此时在这个函数中调用next函数
// 就执行下一个函数(这个函数里面有异步操作)
// 第一个中间件函数应该等待着第二个中间件函数执行,不然就在第二个中间件await的时候直接执行下一部
// 在内部会把这些中间件包装成promise
app.use(async (ctx,next)=>{
console.log(1);
await next(); // 我们在这调用next方法
console.log(2);
});
app.use(async (ctx,next)=>{
console.log(3);
await log(); //等待log执行
await next();
console.log(4)
})
koa中间件
Koa 的最大特色,也是最重要的一个设计,就是中间件(middleware) koa常用的中间件有
koa-bodyparser /koa.js并没有内置Request Body的解析器,当我们需要解析请求体时需要加载额外的中间件,官方提供的koa-bodyparser是个很不错的选择,支持x-www-form-urlencoded, application/json等格式的请求体,但不支持form-data的请求体,需要借助 formidable 这个库,也可以直接使用 koa-body 或 koa-better-body
koa-better-body /处理数据使用
koa-static Node.js除了处理动态请求,也可以用作类似Nginx的静态文件服务,在本地开发时特别方便,可用于加载前端文件或后端Fake数据,可结合 koa-compress 和 koa-mount 使用。/
koa-views koa-views对需要进行视图模板渲染的应用是个不可缺少的中间件,支持ejs, nunjucks等众多模板引擎。/
koa-session Node.js除了处理动态请求,也可以用作类似Nginx的静态文件服务,在本地开发时特别方便,可用于加载前端文件或后端Fake数据,可结合 koa-compress 和 koa-mount 使用。/
koa-router 路由是Web框架必不可少的基础功能,koa.js为了保持自身的精简,并没有像Express.js自带了路由功能,因此koa-router做了很好的补充,作为koa星数最多的中间件,koa-router提供了全面的路由功能,比如类似Express的app.get/post/put的写法,URL命名参数、路由命名、支持加载多个中间件、嵌套路由等。其他可选路由中间件:koa-route, koa-joi-router, koa-trie-router /
koa-bodyparser
1.中间件使用
let bodyParser = require('koa-bodyparser') app.use(bodyParser())
2.原理简单实现
let Koa = require('koa');
let app = new Koa();
app.use(async(ctx, next) => {
if (ctx.path === '/' && ctx.method === 'GET') {// get请求3000
ctx.set('Content-Type', 'text/html;charset=utf8');
ctx.body = `
<form action="/" method="post" >
<input type="text" name="username" autoComplete="off">
<input type="text" name="password" autoComplete="off">
<input type="submit" >
</form>
`
} else {
next();// 提交表单后变成post请求走到post请求的中间件里
}
});
function bodyParser(ctx) {
return new Promise((resolve, reject) => {
let arr = [];
ctx.req.on('data', function(data) {
arr.push(data);
});
ctx.req.on('end', function() {
let body = Buffer.concat(arr).toString();
resolve(body)
})
})
}
app.use(async(ctx, next) => {
if (ctx.method === 'POST' && ctx.path === '/') {
// 获取表单提交过来的数据
ctx.body = await bodyParser(ctx);
//将post的请求data数据赋给ctx.
}
})
app.listen(3000);