1、简单的小示例
const Koa=require('koa'); //引入Koa.js
const app=new Koa(); //实例化Koa对象
const main=ctx=>{ //main函数用来设置ctx.response.body
ctx.response.body='Hello World'; //context.response.body就是发给用户的消息
}
app.use(main); //加载main函数
app.listen(3000); //创建服务器并监听3000端口
2、HTTP Response 的类型
//Koa 默认的返回类型是text/plain,如果想返回其他类型的内容,可以先用ctx.request.accepts判断一下,客户端希望接受什么数据(根据 HTTP Request 的Accept字段),然后使用ctx.response.type指定返回类型
const Koa=require('koa');
const app=new Koa();
const main=ctx=>{
if(ctx.require.accepts('xml')){
ctx.response.type='xml';
ctx.response.body='Hello'
}else if(ctx.require.accepts('json')){
ctx.response.type='json';
ctx.response.body={data:'Hello'};
}else if(ctx.require.accepts('html')){
ctx.response.type='html';
ctx.response.body='Hello
'
}else{
ctx.response.type='text';
ctx.response.body='Hello';
}
}
app.use(main);
app.listen(3000);
3、路由(封装好的 koa-route模块)
const Koa=require('koa');
const app=new Koa();
const route=require('koa-route');
const about=ctx=>{
ctx.response.type='html'; //给客户端发送的消息类型是html
ctx.response.body='去首页' //发送的内容
}
const main=ctx=>{
ctx.response.type='html';
ctx.response.body='我是首页
'
}
app.use(route.get('/',main)); //当客户端访问根路径时,返回main函数
app.use(route.get('/about',about));
app.listen(3000);
4、 静态资源
//如果网站提供静态资源(图片、字体、样式表、脚本......),不必为它们一个个写路由,koa-static模块封装了这部分的请求
const path=require('path');
const serve=require('koa-static');
const main=serve(path.join(__dirname));
app.use(main);
5、重定向
//有些场合,服务器需要重定向(redirect)访问请求。比如,用户登陆以后,将他重定向到登陆前的页面。ctx.response.redirect()方法可以发出一个 302 跳转,将用户导向另一个路由。
const Koa=require('koa');
const app=new Koa();
const route=require('koa-route');
const redirect=ctx=>{
ctx.response.redirect('/'); //将用户重定向到首页
}
const main=ctx=>{
ctx.response.type='html';
ctx.response.body='首页';
}
app.use(route.get('/redirect',redirect));
app.use(route.get('/',main));
app.use(main);
app.listen(3000);
6、中间件
1、打印日志(Logger功能):
const main=ctx=>{
cxt.response.body='Hello';
console.log(`${Date.now()} ${ctx.request.method} ${ctx.request.url}`) //1502144902843 GET /
}
2、什么是中间件?
//基本上,Koa 所有的功能都是通过中间件实现的。
//代码中的logger、main函数就叫做中间件(middleware),因为它处在 HTTP Request 和 HTTP Response 中间,用来实现某种中间功能。app.use()用来加载中间件
//每个中间件默认接受两个参数,第一个参数是 Context 对象,第二个参数是next函数。只要调用next函数,就可以把执行权转交给下一个中间件
const logger=(ctx,next)=>{
console.log(`${Date.now()} ${ctx.request.method} ${ctx.request.url}`)
}
const main=ctx=>{
ctx.response.body='Hello
';
}
app.use(logger);
app.use(main);
app.listen(3000);
3、异步中间件
const fs=require('fs.promised');
const Koa=require('koa');
const app=new Koa();
const main=async function(ctx,next){ //async表示该函数时异步函数(ES6语法)
ctx.response.type='html';
ctx.response.body=await fs.readFile('./demos/template.html','utf8')
}
app.use(main);
app.listen(3000);
4、中间件的合成
//koa-compose模块可以将多个中间件合成为一个
const Koa=require('koa');
const app=new Koa();
const compose=require('koa-compose');
const logger=(ctx,next)=>{
console.log(`${Date.now()} ${ctx.request.method} ${ctx.request.url}`);
next()
}
const main=ctx=>{
ctx.response.body='Hello';
}
const middlewares=compose([logger,main]);
app.use(middlewares);
7、错误处理
1、抛出 500错误、404错误
const main=ctx=>{
ctx.response.status=404; //等同于:ctx.throw(404)
ctx.response.body='找不到页面';
}
2、处理错误的中间件
//main函数抛出错误,被handler函数捕获
const handler=async function(ctx,next){
tr{
await next();
}catch(err){
ctx.response.status=err.statusCode||err.status||500;
ctx.response.body={
message:err.message
}
}
}
const main=ctx=>{
ctx.throw(500);
}
app.use(handler);
app.use(main);
3、error 事件的监听
//运行过程中一旦出错,Koa 会触发一个error事件。监听这个事件,也可以处理错误
const main=ctx=>{
ctx.throw(500);
}
app.on('error',(err,ctx)=>{
console.error('服务器出错了',err)
})
4、释放error事件
//如果错误被try...catch捕获,就不会触发error事件,这时,必须调用ctx.app.emit(),手动释放error事件,才能让监听函数生效
const handler = async (ctx, next) => {
try {
await next();
} catch (err) {
ctx.response.status = err.statusCode || err.status || 500;
ctx.response.type = 'html';
ctx.response.body = 'Something wrong, please contact administrator.
';
ctx.app.emit('error', err, ctx);
}
};
const main = ctx => {
ctx.throw(500);
};
app.on('error', function(err) {
console.log('logging error ', err.message);
console.log(err);
});
8、Web App 的功能
1、Cookies
//ctx.cookies.get('cookieName') 用来读 Cookie
//ctx.cookies.set('cookieName',value) 用来写Cookie
const main=ctx=>{ //你会看到1 views。刷新一次页面,就变成了2 views
const n=Number(ctx.cookies.get('view')||0)+1;
ctx.cookies.set('view',n);
ctx.response.body=n+'view';
}
2、表单
//koa-body模块可以用来从 POST 请求的数据体里面提取键值对
const Koa = require('koa');
const koaBody = require('koa-body');
const app = new Koa();
const main = async function(ctx) {
const body = ctx.request.body;
if (!body.name){
ctx.throw(400, '.name required');
}
ctx.body = { name: body.name };
};
app.use(koaBody());
app.use(main);
app.listen(3000);
3、文件上传
const os = require('os');
const path = require('path');
const koaBody = require('koa-body');
const main = async function(ctx) {
const tmpdir = os.tmpdir();
const filePaths = [];
const files = ctx.request.body.files || {};
for (let key in files) {
const file = files[key];
const filePath = path.join(tmpdir, file.name);
const reader = fs.createReadStream(file.path);
const writer = fs.createWriteStream(filePath);
reader.pipe(writer);
filePaths.push(filePath);
}
ctx.body = filePaths;
};
app.use(koaBody({ multipart: true }));
参考自阮一峰的网络日志