express源码实现1——基础实现

express是什么

express之于nodeJS相当于jQuery之于JS。是一款后端框架(我个人觉得更应该是一个库),能用更简洁的代码量实现原生nodeJS中的效果。

本篇文章的目的

实现express中最主要的方法——创建服务器,监听端口,接收各种前端请求。

流程

  1. 分析express调用方法
    1
    2
    3
    4
    5
    6
    7
    var express=require('express');
    var app=express();
    //监听8080端口,启动服务器
    app.listen(8080);
    app.get('/',function (req,res) {
    //代码
    })

从调用方法来看,express是一个函数,我们需要取得的是express的返回值。该返回值上的listen方法启动服务器并监听端口。该返回值有get、post、put等方法用来接收相应方法的请求。

  • 代码实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    //1.定义express函数
    var express=function() {
    //5.定义app函数,因为被作为createServer()的回调函数传入,所以接收req、res两个参数
    var app=function (req,res) {}
    //6.路由路由池,存放各种请求,用以在适当时候加载
    app.routes=[];
    //7.定义各种请求方法对应的函数
    var methods=['get','post','put','options','delete','all'];
    methods.forEach(function (method) {
    //各种方法的函数接收两个参数 路径 与回调函数
    app[method]=function (path,fn) {
    //将方法,路径与回调函数全部放入方发池
    var config={method:method,path:path,fn:fn};
    routes.push(config);
    }
    })
    //4.定义返回值上的listen方法
    app.listen=function (port) {
    //启动服务器,监听端口,返回值作为createServer()的回调函数传入
    require('http').createServer(app).listen(port);
    }
    //3.返回方法
    return app;
    }
    //2.暴露接口
    module.exports=express;
  1. 当请求到来时将请求与路由池中保存的请求匹配,匹配上就执行相应回调函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //第5步定义的函数
    var app=function (req,res) {
    //取得请求中的方法名和路径
    var method=req.method;
    var urlObj=require('url').parse(req.url,true);
    var pathname=urlObj.pathname;
    //将请求的方法名与路径与路由池中保存的匹配
    var route=app.routes.find(function (route) {
    //返回路径与方法都匹配项,其中method=='all'能匹配所有方法,path=="*"能匹配所有路径
    return (route.method==method||route.method=="all")&&(route.path==pathname||route.path=="*")
    })
    //如果匹配到,就执行该路由的回调函数,传入req和res
    if (route) {
    route.fn(req,res);
    } else {
    //未匹配到则在页面上显示相应信息
    res.end(`Cannot ${method} ${pathname}`)
    }
    }