1. 程式人生 > >Koa入門和原始碼分析

Koa入門和原始碼分析

1:koa入門
初始化檔案 npm init
安裝koa  npm install koa –save
(1)Hello world練習
const Koa = require("koa");

const app = new Koa(); //app是應用的起步
app.use(async(ctx,next) =>{  //ctx封裝的是request 和 response
    ctx.body = "hello world"  //next封裝的是一下箇中間件
})
app.listen(3000);

2:原理封裝實現
(1)	Hello world淺層原理實現
const http = require('http')
const server =  http.createServer((req,res)=>{
    res.writeHead(200)
    res.end("hello world ")
})
server.listen(8088)
 
//封裝use,listen方法
const Woa = require('./application')
const app = new Woa()
app.use((req,res)=>{
    res.writeHead(200)
    res.end("hello server")
})

app.listen(8088)

const http = require('http')
class Application{
 
    constructor(){
        this.callback = ()=>{}
    }
    use(callback){
        this.callback = callback
    }
    listen(...args){
        const server = http.createServer((req,res)=>{
            this.callback(req,res)
            server.listen(...args)
        })
    }
}
module.exports = Application

(2)	context封裝
構建ctx 
掛載request和response物件
Ctx.body = xx 就可以修改相應 如何做到
Js的getter 和setter


(3)同步的compose實現原理(中介軟體)
function add(x,y){
  return x+y
}
function double(z){
  return z*2
}
const res1 = add(1,2)
const res2 = double(res1)
console.log(res2)

const res3 = double(add(1,2))
console.log(res3)
const middlewares = [add, double]
let len = middlewares.length
function compose(midds){
  return (...args)=>{
    // 初始值
    let res = midds[0](...args)
    for(let i=1;i<len;i++){
      res = midds[i](res)
    }
    return res
  }
}
const fn = compose(middlewares)
const res = fn(1,2)
console.log(res)

(3)	非同步有序執行中介軟體(next實現原理遞迴)

async function fn1(next){
  console.log('fn1')
  await next()
  console.log('end fn1')
}

async function fn2(next){
  console.log('fn2')
  await delay()
  await next()
  console.log('end fn2')
}
function fn3(next){
  console.log('fn3')
}

function delay(){
  return new Promise((reslove,reject)=>{
    setTimeout(()=>{
      reslove()
    },2000)
  })
}

function compose (middlewares){
  return function(){
    return dispatch(0)
    function dispatch(i){
      let fn = middlewares[i]
      if(!fn){
        return Promise.resolve()
      }
      return Promise.resolve(fn(function next(){
        return dispatch(i+1)
      }))
    }
  }
}

const middlewares = [fn1,fn2,fn3]
const finalFn = compose(middlewares)
finalFn()



(4)	完整實現簡單的koa
const http = require('http')
let request = {
  get url(){
    return this.req.url
  }
}
let response = {
  get body(){
    return this._body
  },
  set body(val){
    this._body = val
  }
}

let context = {
  get url(){
    return this.request.url
  },
  get body(){
    return this.response.body
  },
  set body(val){
    this.response.body = val
  }
}
class Application {
  constructor(){
    // this.callback = ()=>{}
    this.context = context
    this.request = request
    this.response = response
    this.middlewares = []
  }
  use(callback){
    this.middlewares.push(callback)
    // this.callback = callback
  }
  compose (middlewares){
    return function(context){
      return dispatch(0)
      function dispatch(i){
        let fn = middlewares[i]
        if(!fn){
          return Promise.resolve()
        }
        return Promise.resolve(fn(context,function next(){
          return dispatch(i+1)
        }))
      }
    }
  }
  listen(...args){
      const server = http.createServer(async(req,res)=>{
      let ctx = this.createCtx(req,res)
      const fn = this.compose(this.middlewares)
      await fn(ctx)
      ctx.res.end(ctx.body)
      // this.callback(req,res)
    })
    server.listen(...args)
  }
  createCtx(req, res){
    let ctx = Object.create(this.context)
    ctx.request = Object.create(this.request)
    ctx.response = Object.create(this.response)
    ctx.req = ctx.request.req = req
    ctx.res = ctx.response.res = res
    return ctx
  }
}
module.exports = Application

//server.js
const Woa = require('./application')
const app = new Woa()
function delay(){
  return new Promise((reslove,reject)=>{
    setTimeout(()=>{
      reslove()
    },2000)
  })
}

app.use(async (ctx,next)=>{
  ctx.body = '1'
  await next()
  ctx.body += '2'
})
app.use(async (ctx,next)=>{
  ctx.body += '3'
  await delay()
  await next()
  ctx.body += '4'
})
app.use(async (ctx,next)=>{
  ctx.body += '5'
})
// app.use((req, res)=>{
//   res.writeHead(200)
//   res.end('hello imooc')
// })
app.listen(9092,()=>{
  console.log('server runing on port 9092')
})