koa基础

Posted aymfx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了koa基础相关的知识,希望对你有一定的参考价值。

前言

作为express框架的继承者koa,好像拥有了更多的优势了,体积更小,没有绑定任何多余的中间件,提供了一套优雅的方式async await 来操作中间件(由于koa2是基于async/await操作中间件,目前node.js 7.x的harmony模式下才能使用),采用类似堆栈的方式,先进后出的方式,一步步处理数据

参考 :https://chenshenhai.github.io/koa2-note/

写一个hello world

 
   
   
 
  1. const koa = require('koa')

  2. const app = new koa();

  3. app.use(async (ctx)=>{

  4.  ctx.body = "hello,world";

  5. })

  6. app.listen(4000)

洋葱处理图

下面这个例子很好的解释了为啥叫洋葱图了

 
   
   
 
  1. const Koa = require('koa');

  2. const app = new Koa();

  3. // logger

  4. app.use(async (ctx, next) => {

  5.  console.log("1")

  6.  await next();

  7.  console.log("2")

  8.  const rt = ctx.response.get('X-Response-Time');

  9.  console.log(`${ctx.method} ${ctx.url} - ${rt}`);

  10. });

  11. // x-response-time

  12. app.use(async (ctx, next) => {

  13.  const start = Date.now();

  14.  console.log("3")

  15.  await next();

  16.  console.log("4")

  17.  const ms = Date.now() - start;

  18.  ctx.set('X-Response-Time', `${ms}ms`);

  19. });

  20. // response

  21. app.use(async ctx => {

  22.  console.log(5)

  23.  ctx.body = 'Hello World';

  24. });

  25. app.listen(3000);

  26. /*

  27. 1

  28. 3

  29. 5

  30. 4

  31. 2

  32. GET / - 3ms

  33. */

先进入第一个中间件,然后输出1 ,调用了es6的语法,等待下一个中间件返回结果,然后进入了第二个中间件,这里执行了3,然后又进入了下一个中间件,执行了5,这个中间的代码执行完返回上一个中间件继续往下走于是输出4,又继续返回上一个中间件,输出2 ,结果就是 13542 ,这就是类似于洋葱的结构图了

写一个简单的中间件

对于koa的中间件都必须采用es7的async await写法来写

 
   
   
 
  1. //简单的打印日志

  2. // --- log.js

  3. function log(ctx){

  4.      console.log("打印下",ctx.method,ctx.host,ctx.url)

  5. }

  6. module.exports = function(){

  7.    return async function(ctx,next) {

  8.          log(ctx);

  9.          await next();

  10.    }

  11. }

  12. // app.js

  13. const Koa = require('koa');

  14. const app = new Koa();

  15. const log = require('./log')

  16. app.use(log())

  17. app.use(async ctx => {

  18.  console.log(5)

  19.  ctx.body = 'Hello World';

  20. });

  21. app.listen(3000);

对于generate语法,我们需要一个方法进行转换

  • const convert = require('koa-convert')

写一个原生的路由

 
   
   
 
  1. //app.js

  2. const Koa = require('koa');

  3. const app = new Koa();

  4. const route = require('./route')

  5. app.use(async ctx => {

  6.      let html = await route(ctx);

  7.      console.log(html,1995)

  8.      ctx.body =html;

  9. });

  10. app.listen(3000);

  11. // route.js

  12. const fs = require("fs")

  13. function getHtml(ctx) {

  14.  return new Promise((res, rej) => {

  15.    console.log("dasdasd")

  16.    console.log(ctx.request.url)

  17.    let path = "./views"

  18.    if (ctx.request.url == "/") {

  19.      path += '/index.html'

  20.    } else {

  21.      path = `${path}${ctx.request.url}.html`

  22.    }

  23.    if (!(fsExistsSync(path))) {

  24.      path = "./views/404.html"

  25.    }

  26.    console.log(path)

  27.    fs.readFile(path,"utf-8", (err, data) => {

  28.      if (err) {

  29.        console.log("出错了")

  30.        rej(err)

  31.      }

  32.      console.log(data)

  33.      res(data)

  34.    })

  35.  })

  36. }

  37. // 检测目录是否存在

  38. function fsExistsSync(path) {

  39.  try {

  40.    fs.accessSync(path, fs.F_OK);

  41.  } catch (e) {

  42.    return false;

  43.  }

  44.  return true;

  45. }

  46. module.exports = async function (ctx) {

  47. return  await getHtml(ctx);

  48. }

  49. //自己再写个views目录,下面放几个html

koa的路由的写法

 
   
   
 
  1. const Koa = require('koa');

  2. const router = require("koa-router");

  3. const app = new Koa();

  4. // 一个子路由

  5. const home = new router();

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

  7.     let html = `<ul><li><a href="/">首页</a></li><li><a href="/page/about">关于</a></li></ul>`;

  8.     ctx.body = html;

  9. })

  10. //第二个子路由

  11. const about = new router();

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

  13.     let html = `我是about`;

  14.     ctx.body = html;

  15. }).get('/404',async(ctx)=>{

  16.  let html = `我是404`;

  17.  ctx.body = html;

  18. }

  19. )

  20. // 装载两个路由

  21. const route = new router();

  22. route.use('/',home.routes(),home.allowedMethods())

  23. route.use('/page',about.routes(),about.allowedMethods())

  24. // 加载路由中间件

  25. app.use(route.routes()).use(route.allowedMethods())

  26. app.listen(3000);

获取get请求的参数

通过ctx.query,ctx.querystring,以及ctx.request.query,ctx.request.querystring来获取

 
   
   
 
  1. const Koa = require('koa');

  2. const app = new Koa();

  3. app.use(async ctx =>{

  4.  let url = ctx.url

  5.  let requst_query = ctx.request.query

  6.  let requst_querystring = ctx.request.querystring;

  7.  let query = ctx.query;

  8.  let querystring = ctx.querystring;

  9.  ctx.body = {

  10.    url,

  11.    requst_query,

  12.    requst_querystring,

  13.    query,

  14.    querystring

  15.  }

  16. })

  17. app.listen(3000);

对于post请求,koa没有很好的处理,我们需要自己用原生方法将他封装自己想要的东西

 
   
   
 
  1. const Koa = require('koa');

  2. const app = new Koa();

  3. app.use(async ctx => {

  4.  if (ctx.url == '/' && ctx.method==="GET") {

  5.    let html = `

  6.         <h1>koa2 request post demo</h1>

  7.         <form method="POST" action="/api/data">

  8.            <p>userName</p>

  9.            <input name="userName" /><br/>

  10.            <p>nickName</p>

  11.            <input name="nickName" /><br/>

  12.            <p>email</p>

  13.            <input name="email" /><br/>

  14.            <button type="submit">submit</button>

  15.          </form>

  16.          `;

  17.      ctx.body = html

  18.  }else if(ctx.url == '/api/data' && ctx.method==="POST"){

  19.      let postData = await parsePostData(ctx);

  20.      ctx.body =postData

  21.  }else{

  22.      ctx.body = "有错误啊"

  23.  }

  24. })

  25. function parsePostData(ctx){

  26.  return new Promise((res,rej)=>{

  27.      try {

  28.        let postdata = "";

  29.        ctx.req.addListener('data',data=>{

  30.          postdata +=data;

  31.        })

  32.        ctx.req.addListener('end',()=>{

  33.          res(parseQueryStr(postdata))

  34.        })

  35.      } catch (error) {

  36.          rej(error)

  37.      }

  38.  })

  39. }

  40. function parseQueryStr(querystr){

  41.     let queryData = {};

  42.     let queryStrList = querystr.split('&')

  43.     console.log(queryStrList);

  44.     for (const [index,queryStr] of queryStrList.entries()) {

  45.        let itemList = queryStr.split('=');

  46.        queryData[itemList[0]] = decodeURIComponent(itemList[1])

  47.     }

  48.     return queryData;

  49. }

  50. app.listen(3000);

第三方插件助力post请求

 
   
   
 
  1. const Koa = require('koa');

  2. const app = new Koa();

  3. const bodyParser = require('koa-bodyparser')

  4. app.use(bodyParser())

  5. app.use(async ctx => {

  6.  if (ctx.url == '/' && ctx.method==="GET") {

  7.    let html = `

  8.         <h1>koa2 request post demo</h1>

  9.         <form method="POST" action="/api/data">

  10.            <p>userName</p>

  11.            <input name="userName" /><br/>

  12.            <p>nickName</p>

  13.            <input name="nickName" /><br/>

  14.            <p>email</p>

  15.            <input name="email" /><br/>

  16.            <button type="submit">submit</button>

  17.          </form>

  18.          `;

  19.      ctx.body = html

  20.  }else if(ctx.url == '/api/data' && ctx.method==="POST"){

  21.      let postData =ctx.request.body

  22.      ctx.body =postData

  23.  }else{

  24.      ctx.body = "有错误啊"

  25.  }

  26. })

  27. app.listen(3000);


以上是关于koa基础的主要内容,如果未能解决你的问题,请参考以下文章

Node.js 蚕食计划—— Koa 基础项目搭建

1koa的安装,get和post方法的基础使用

koa基础

十分钟带你看完 KOA 源码

01-koa2基础

Koa笔记 02:常用中间件