请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

视频中的express中间件实现方案有点问题, 还可以优化一下

视频中的方案, 如果测试case如下:

app.use((req, res, next) => {
  console.log("1 use...");
  next();
});

app.get((req, res, next) => {
  // 假设在处理 cookie
  console.log("2 get...");
  next();
});

app.use("/api", (req, res, next) => {
  console.log("3 use...");
  next();
});

结果:

1 use...
3 use...
2 get...

而期望应该是:

1 use...
2 get...
3 use...

正在回答 回答被采纳积分+3

2回答

提问者 GivenCui 2019-06-22 17:16:38
/* 我的实现思路: */

// like-express.js

const http = require("http");
const slice = Array.prototype.slice;

class Express {
    constructor() {
        this.stacks = [];
    }
    _isMatch(req, stack) {
        if (req.url === "/favicon.ico") {
            return false;
        }
        if (req.url.indexOf(stack.path) === 0) {
            if (req.method.toLowerCase() === stack.method || stack.method === "all") {
                return true;
            }
        }
        return false;
    }
    _resgister(method, args) {
        if (typeof args[0] === "string") {
            this.stacks.push({
                path: args[0],
                middleware: slice.call(args, 1),
                method
             });
        } else {
            this.stacks.push({
                path: "/",
                middleware: slice.call.call(args),
                method
            });
        }
    }
    use() {
        this._resgister("all", arguments);
    }
    get() {
        this._resgister("get", arguments);
    }
    post() {
        this._resgister("post", arguments);
    }
    _trigger(req, res) {
        const finalStacks = [];
        this.stacks.forEach(stack => {
            if (this._isMatch(req, stack)) {
                finalStacks.push(...stack.middleware);
            }
        });
        const next = () => {
            const cb = finalStacks.shift();
            if (cb) {
                cb(req, res, next);
            }
        };
        next();
    }
    _serverHandle(req, res) {
        res.json = data => {
            res.setHeader("content-type", "application/json");
            res.end(JSON.stringify(data));
        };
        this._trigger(req, res);
    }
    listen() {
        // 利用箭头函数在定义时绑定
        const server = http.createServer((req, res) => {
            // console.log("this === http", this === http); // false
            // console.log("this intanceof Express", this instanceof Express); // true
            this._serverHandle(req, res);
        });
        server.listen(...arguments);
    }
}

module.exports = function() {
    return new Express();
};
// test.js

const expressLike = require("./like-express");

const app = expressLike();

app.use("/", (req, res, next) => {
    console.log(1, "use 开始");
    next();
    console.log(1, "use 结束");
    res.json({
        say: "Hello World"
    });
});
app.get("/test", (req, res, next) => {
    console.log(2, "get 开始");
    next();
    console.log(2, "get 结束");
});
app.post("/test", (req, res, next) => {
    console.log(3, "post 开始");
    next();
    console.log(3, "post 结束");
});
app.use("/test", (req, res, next) => {
    console.log(4, "use 开始");
    next();
    console.log(4, "use 结束");
});
app.listen("1314", () => {
    console.log("server is running on PORT 1314");
});


测试链接: `http://localhost:1314/test`,  输出:

1 'use 开始'
2 'get 开始'
4 'use 开始'
4 'use 结束'
2 'get 结束'
1 'use 结束'


9 回复 有任何疑惑可以回复我~
  • middleware: slice.call.call(args), 多写了一个call
    回复 有任何疑惑可以回复我~ 2020-11-12 11:14:26
  • slice.call.call(args) 多写了一个call
    回复 有任何疑惑可以回复我~ 2020-11-12 11:20:05
  • 执行顺序:
    1 use 开始
    4 use 开始
    2 get 开始
    2 get 结束
    4 use 结束
    1 use 结束
    回复 有任何疑惑可以回复我~ 2020-11-12 11:20:46
双越 2019-06-22 17:22:32

感谢反馈,很赞。可以发到 qq 群分享一下。

1 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信