手撕源码系列:80行代码实现express框架

232次阅读  |  发布于3年以前
const express = require("express");
const app = express();

app.get("/test", (req, res, next) => {
  console.log("会所技师到位*1");
//   res.end("会所技师开始服务1");
  next();
});

app.get("/test", (req, res, next) => {
  console.log("会所技师到位*2");
  res.end("会所技师开始服务2");
});

app.listen(8888, (err) => {
  !err && console.log("会所里面有大保健吗?");
});
会所技师到位*1
会所技师到位*2

一起来实现一个简单的express框架

class express {

}

module.exports = express;
const { createServer } = require("http");
class express {
  listen(...args) {
    createServer(cb).listen(...args);
  }
}

实现接收到请求触发

class express {
  cb() {
    return (req, res) => {
      console.log(res, res, "来客人了");
    };
  }
  listen(...args) {
    createServer(this.cb()).listen(...args);
  }
}

  constructor() {
    this.routers = {
      get: [],
      post: [],
    };
  }

  get(path, handle) {
    this.routers.get.push({
      path,
      handle,
    });
  }
  post(path, handle) {
    this.routers.post.push({
      path,
      handle,
    });
  }
  cb() {
    return (req, res) => {
      const method = req.method.toLowerCase();
      console.log(this.routers[method], ",method");
      const url = req.url;
      this.routers[method].forEach((item) => {
        item.path === url && item.handle(req, res);
      });
    };
  }
  listen(...args) {
    createServer(this.cb()).listen(...args);
  }
[ { method: 'get', path: '/test', handle: [Function] } ] ,method

完成最重要的中间件功能

 constructor() {
    this.routers = {
      get: [],
      post: [],
      all: [],
    };
  }
  handleAddRouter(path, handle) {
    let router = {};
    if (typeof path === "string") {
      router = {
        path,
        handle,
      };
    } else {
      router = {
        path: "/",
        handle: path,
      };
    }
    return router;
  }

  get(path, handle) {
    const router = this.handleAddRouter(path, handle);
    this.routers.get.push(router);
  }

  post(path, handle) {
    const router = this.handleAddRouter(path, handle);
    this.routers.post.push(router);
  }

  use(path, handle) {
    const router = this.handleAddRouter(path, handle);
    this.routers.all.push(router);
  }

❝这里要注意,promise.then 源码实现和 express 的 next、以及 koa 的洋葱圈、redux 的中间件实现,有着一丁点相似,当你能真的领悟前后端框架源码时候,发现大都相似

实现next

  search(method, url) {
    const matchedList = [];
    [...this.routers[method], ...this.routers.all].forEach((item) => {
      item.path === url && matchedList.push(item.handle);
    });
    return matchedList;
  }

  cb() {
    return (req, res) => {
      const method = req.method.toLowerCase();
      const url = req.url;
      const matchedList = this.search(method, url);
    };
  }
  handle(req, res, matchedList) {
    const next = () => {
      const midlleware = matchedList.shift();
      if (midlleware) {
        midlleware(req, res, next);
      }
    };
    next();
  }
  cb() {
    return (req, res) => {
      const method = req.method.toLowerCase();
      const url = req.url;
      const matchedList = this.search(method, url);
      this.handle(req, res, matchedList);
    };
  }

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8