阅读 545

面试题之你了解Koa吗

介绍

来自官方文档简介:Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。

Koa和原生http的区别

Koa的优势在于显著的提高开发效率,在koa中中间件的概念很明显。中间件有 listen,use,ctx,next 。Koa为什么可以提高效率?我们来分析一下它的源码。

源码分析

中间件 listen

listen中间件就是一个语法糖,其实他里面还是http的listen,只是包装的一层。

listen(...args){
        let server=http.createServer(this.handleRequest.bind(this));
        server.listen(...args);
    }
复制代码

中间件 use

在我们使用use的时候,会发现里面的函数会立即执行,说明use的源码中有一个回调函数可以让它立即执行。

use(fn){//use里传入回调函数
        this.fn=fn;//执行回调函数,保证其在listen后执行 
    }
复制代码

中间件 ctx

首先我们知道在使用koa的时候,我们不管是请求操作还是响应操作,都是使用ctx调用,这也是Koa框架的优势,让代码更简单。现在我们就来探究一下,ctx是怎么实现的?

创建一个context.js 的文件

//ctx 怎么来的
let proto ={
   // url:request.url
} 
function defineGetter(prop,name){  //代理函数
    proto.__defineGetter__(name,function(){
        return this[prop][name] //this == ctx
    })
}
defineGetter('request','url') // url==request.url
defineGetter('request','path')
module.exports = proto
复制代码

application.js

createContext(req,res){//构建ctx
        const ctx=Object.create(this.context)//使ctx具备三种属性  交叉赋值
        const request=ctx.request=Object.create(this.request)
        const response=ctx.response=Object.create(this.response)
        ctx.req=request.req=response.req=req
        ctx.res=request.res=response.res=res
        request.ctx=response.ctx=ctx
        request.response=response
        response.request=request
        return ctx
    }
复制代码

request.js

//为什么Koa里面没有req
let url=require('url')
let request ={
    // ctx.url == ctx.request.url
    get url(){ //整个地址全拿,包括参数
        console.log(this);
        return this.req.url
    },
    get path(){ //只拿路径名称
        return url.parse(this.req.url).pathname
    }
}

module.exports=request
复制代码

封装Koa模块 application.js

let EventEmitter=require('events')
let http=require('http')
let context=require('./context')
let request=require('./request')
let response=require('./response')

class Koa extends EventEmitter{//继承于event,使我们手写的Koa也能有错误处理机制
    constructor(){ //继承到所有属性  构造函数的继承
        super();//超级继承
        this.fn;
        this.context=context;
        this.request=request;
        this.response=response;
    }

    use(fn){//use里传入回调函数
        this.fn=fn;//执行回调函数,保证其在listen后执行
       
    }

    createContext(req,res){//构建ctx
        const ctx=Object.create(this.context)//使ctx具备三种属性  交叉赋值
        const request=ctx.request=Object.create(this.request)
        const response=ctx.response=Object.create(this.response)
        ctx.req=request.req=response.req=req
        ctx.res=request.res=response.res=res
        request.ctx=response.ctx=ctx
        request.response=response
        response.request=request
        return ctx
    }

    handleRequest(req,res){
        let ctx=this.createContext(req,res)
        this.fn(ctx)//为了方便调用fn,多封装一层
        res.end(ctx.body)
    }

    listen(...args){
        let server=http.createServer(this.handleRequest.bind(this));
        server.listen(...args);
    }
}

module.exports=Koa;
复制代码

总结

虽然这篇文章没有把所有的源码都拿出来分析,但我们知道了中间件 listen,use,ctx 的实现,也是了解Koa的第一步。如果这篇文章让你对Koa的源码感兴趣,点击跳转Koa源码,目前是一名大三学生,初学前端,如果有写的不对的地方,欢迎指正,感谢!

文章分类
前端
文章标签