koa2学习笔记(一)

(1)使用
基本用法:

const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
    ctx.response.type = 'html';
    ctx.response.body =
    fs.createReadStream('./view/include/test.html');
});

配置路由:

    if(ctx.request.path === '/') {
        ctx.response.type = 'html';
        ctx.response.body = '<div>根目录</div>';
    }else {
        ctx.response.body = '哈哈哈,随机路径';
    }

使用koa-router模块:

const Koa = require('koa');
const route = require('koa-route');
const app = new Koa();
var main = ctx => {
    ctx.response.type = 'html';
    ctx.response.body = '<h1>about<h1>';
}
app.use(route.get('/about'), main);
静态资源:  // 直接访问浏览器js代码  可查看
const serve = require('koa-static');
const app = new Koa();
const _static = serve(path.join(__dirname));
app.use(_static);

重定向:

const redirect = ctx => {
    ctx.response.redirect('/');
};
app.use(route.get('/redirect', redirect));

抛错:

ctx.throw(500)  Internal Service Error
ctx.throw(404)  Not Found     
//    相当于: 
ctx.response.status = 404;
ctx.response.body = 'Not Found';
// error事件监听:
const main = ctx => {
    ctx.throw(500);
};
app.on('error',
 (err, ctx) => console.error('server error', err););

throw错误能被error事件捕获,但是try…catch中的错会在catch中处理,必须调用
ctx.app.emit(‘error’, err, ctx);才能触发error事件。

(2)中间件
①同步中间件

const one = (ctx, next) => {
  console.log('>> one');
  next();
  console.log('<< one');
}

const two = (ctx, next) => {
  console.log('>> two');
  next(); 
  console.log('<< two');
}

const three = (ctx, next) => {
  console.log('>> three');
  next();
  console.log('<< three');
}

app.use(one);
app.use(two);
app.use(three);  
打印: 
>> one
>> two
>> three
<< three
<< two
<< one

②异步中间件

const fs = require('fs.promised');     // promise读文件
    const main = async function (ctx, next) {
        ctx.response.body = await fs.readFile('./demos/template.html', 'utf8');
    };

③中间件合成

const middlewares = compose([logger, main]);
app.use(middlewares);

④中间件错误捕获

const handler = async (ctx, next) => {
  try {
    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);

⑤WebApp
1)Cookie
app.use(async ctx => {
    const n = Number(ctx.cookies.get('view') || 0) + 1;
    ctx.cookies.set('view', n);
    ctx.response.body = '<h1>'+ n +'views</h1>'
});
ctx.cookies.set(name, value, [options])

通过 options 设置 cookie name 的 value :
maxAge 一个数字表示从 Date.now() 得到的毫秒数
signed cookie 签名值
expires cookie 过期的 Date
path cookie 路径, 默认是’/’
domain cookie 域名
secure 安全 cookie
httpOnly 服务器可访问 cookie, 默认是 true
overwrite 一个布尔值,表示是否覆盖以前设置的同名的 cookie (默认是 false). 如果是 true, 在同一个请求中设置相同名称的所有 Cookie(不管路径或域)是否在设置此Cookie 时从 Set-Cookie 标头中过滤掉。

2)表单

const koaBody = require('koa-body');

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());

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 }));

(3)http源码

const http = require('http'); 
const https = require('https'); 
const Koa = require('koa');
const app = new Koa(); 
http.createServer(app.callback()).listen(3000); 
https.createServer(app.callback()).listen(3001);

(4)调数据库

app.context.db = db(); 
app.use(async ctx => {
 console.log(ctx.db); 
});

(5)contex
ctx.type 和 ctx.length 委托给 response 对象,ctx.path 和 ctx.method 委托给 request。
node的response和request对象: ctx.res ctx.req
(6)缓存检查
request.fresh
检查请求缓存是否“新鲜”,也就是内容没有改变。此方法用于 If-None-Match / ETag, 和 If-Modified-Since 和 Last-Modified 之间的缓存协商。 在设置一个或多个这些响应头后应该引用它。

// 新鲜度检查需要状态20x或304
ctx.status = 200;
ctx.set('ETag', '123');
// 缓存是好的
if (ctx.fresh) {
  ctx.status = 304;
  return;
}
// 缓存是陈旧的// 获取新数据
ctx.body = await db.find('something');

(7) ctx.accepts()

switch (ctx.accepts('json', 'html', 'text')) { 
case 'json': break; 
case 'html': break;
 case 'text': break; 
default: ctx.throw(406, 'json, html, or text only'); 
}

(8)ctx.acceptsEncodings(‘gzip’, ‘deflate’, ‘identity’);
(9)响应头部

ctx.set('Cache-Control', 'no-cache');
ctx.set({ 
    'Etag': '1234',
    'Last-Modified': date 
});

(10)if (!ctx.response.is(‘html’)) return;
(11)

ctx.response.etag = 
crypto.createHash('md5').update(ctx.body).digest('hex');

猜你喜欢

转载自blog.csdn.net/weixin_39265000/article/details/81052575