Koa-1

爲什麼要學 Koa,不學 Express

因爲不想寫回調,日常開發習慣 async await 處理異步流程,因此選擇 Koa 2。(以下簡稱 Koa)

Koa2 核心概念

洋蔥模型 其實就是 async await 執行流程,在 koa 每次調用中間件時,回調函數中 next 會吧執行權遞交給下一個回調函數。按筆者通俗的解釋爲:洋蔥先從外側切到內側,再從內測切到另一邊的外側。其實也就是回調函數被 async await 化了而已。
ctx(context) 上下文,request, response 都被合併封裝到 ctx 中,方便每個中間件進行操作,調用。
​​​​Demo
打印一下 ctx,可見,ctx 描述的是,每個完整的 http 所包含的信息,包括但不限於 請求方法(method),url(request url),響應碼(status), 響應信息 message, header 等。

路由 路由的處理也是包含在中間件中的。路由的概念並不陌生,Angular 中除了基本的 Router 路由器讓你處理跳轉路由之外,還有 Activeted 路由,來處理不同的 Url 和接受 query 等。 在我看來,這裏 Koa 的路由,其實跟 Angular Activeted 的概念很像。代碼:

// 根路由
app.use(async (ctx, next) => {
    if(ctx.request.path === '/') {
        ctx.response.body = '<h1>index Router</h1>';
    }
    else {
       await next();
    }
});

// todo 路由
app.use(async (ctx, next) => {
    if(ctx.request.path === '/todo') {
        ctx.response.body = '<h1>Todo Router</h1>';
    }
    else {
       await next();
    }
});

完事。 Demo:

Demo

但官方已經有更好的中間件了:koa-router

const Koa = require('koa');
const app = new Koa();
const router = require('koa-router')()

// 根路由
router.get('/', async (ctx, next) => {
  ctx.response.body = '<h1>index Router</h1>';
});

// todo 路由
router.get('/todo', async (ctx, next) => {
    ctx.response.body = '<h1>Todo Router</h1>';
});

app.use(router.routes());	

具名路由:

// 給路由起個名字,便於複用

router.get('user', 'users/:id', async (ctx, next) => {

    ctx.response.body = `你要訪問的是 : ${ctx.response.path}`;
});

query param 以及 param 對象


// params
router.get('/home/:id', async (ctx,next) => {
ctx.response.type = 'application/json';
ctx.response.body = ctx.params;
});

// query-params
router.get('/home' async (ctx, next) => {
ctx.response.type = 'application/json';
ctx.response.body = `${ctx.request.query}`;
});

params:-object:
(param-object
query-params:
query-params
Angular 中的路由做一下類比:

// 形如 /home/:id 
this.activitedRoute.paramMap.subscribe( param => console.log(param)); // {"id": "4"}  

// 形如 /home?a=1&b=2
this.route.queryParamMap.subscribe(res => console.log(res)); // map<string,number> = new Map({a: 1, b:2}); 

都是根據瀏覽器的 urlParamsMap 來實現的。

body-parser

上述的所有請求, 都是基於 GET 請求的,那麼如果客戶端發來 post 請求,怎麼解析 send 過來的數據呢?通過路由嗎?做不到啊!所以還是得藉助 ctx 上掛着的的對象來進行解析,因爲 post 請求接受 form Data 也是異步的,所以要給 ctx.request 綁定監聽:

const Koa = require('koa')
const router = require('koa-router')()
const app = new Koa()

// 通用路由,直接給出 form 表單,誘導進一步的 post 操作
app.use(async (ctx, next) => {
  ctx.body = `
    <form action="/submit" method="post">
      <input name="account" type="text"> 賬號
      <br/>
      <input name="password" type="password"> 密碼
      <br/>
      <button>提交</button>
    </form>
  `;
  await next();
});

// 進行 post 操作時的 middleware
app.use(async (ctx, next) => {
  if (ctx.request.url === '/submit') {
    // ctx.response.type = 'application/json';
    const data = await parseData(ctx);
    ctx.response.body = data;
  }
  await next();
});

// 接收上下文,通過 事件監聽 和 promise 來達到解析數據的目的 
function parseData(ctx) {
  return new Promise((resolve, reject) => {
      try {
          let str = ''
          ctx.req.on('data', (data) => {
              str += data
          })
          ctx.req.addListener('end', () => {
              resolve(str)
          })
      } catch (err) {
          reject(err)
      }
  });
}

// add router middleware:
app.use(router.routes());

app.listen(3000, () => {
  console.log('server is running at http://localhost:3000')
});

Demo: Demo

But, 不用這麼麻煩,有對應的輪子了: koa-bodyparser 該中間件,會將 post 的數據,全部解析進 ctx.request.body
核心代碼:

const bodyparser = require('koa-bodyparser');
// 直接使用中間件
app.use(bodyparser());

app.use(async (ctx, next) => {
  ctx.body = `
    <form action="/submit" method="post">
      <input name="account" type="text"> 賬號
      <br/>
      <input name="password" type="password"> 密碼
      <br/>
      <button>提交</button>
    </form>
  `;
  await next();
});


app.use(async (ctx, next) => {
  if (ctx.request.url === '/submit') {
    // ctx.response.type = 'application/json';
   
    ctx.response.body = ctx.request.body;
  }
  await next();
});

來試試效果吧!
body-parser
搞定了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章