【问题标题】:How to write a middleware class in Node.js如何在 Node.js 中编写中间件类
【发布时间】:2016-09-04 14:34:00
【问题描述】:

我已经在 Google 和书籍上研究了几个小时的主题,但我只能找到非常具体的实现。我正在努力在 node JS 中编写一个简单的中间件类,只有普通的 vanilla javascript(没有像 async、co、.. 这样的附加模块)。我的目标是了解它是如何工作的,而不是获得最优化的代码。

我想要一些简单的东西,比如拥有一个字符串并通过使用中间件向其中添加新字符串。

班级

"use strict";
class Middleware {
    constructor() {
        this.middlewares = [];
    }
    use(fn) {
        this.middlewares.push(fn);
    }
    executeMiddleware(middlewares, msg, next) {
       // This is where I'm struggling
    }
    run(message) {
        this.executeMiddleware(this.middlewares, message, function(msg, next) {
            console.log('the initial message : '+ message);
        });
    }
}
module.exports = Middleware;

一种可能的用法

const Middleware = require('./Middleware');
const middleware = new Middleware();

middleware.use(function(msg, next) {
    msg += ' World';
    next();
});

middleware.use(function(msg, next) {
    msg += ' !!!';
    console.log('final message : ' + msg);
    next();
});
middleware.run('Hello');

因此,msg 变量最终会变成:'Hello World !!!'

【问题讨论】:

  • 你到底在纠结什么?并且(为什么)你需要这门课?
  • @thomas @jfriend00 出于教育目的,我让这个例子超级简单,但它实际上是一个更大的类的一部分。我需要这个中间件模式来根据用户输入信息来扩充 JS 对象,并收集一些数据以便将其保存在数据库中。 我真正苦苦挣扎的executeMiddleware 方法内部的逻辑。我试图通过中间件数组循环并调用每个函数middleware.call(this, arg, next) 问题是,数据不会在中间件之间持续存在。最后一个中间件收到“Hello”而不是“Hello World”。
  • @Thomas 我已经按照您的建议实现了 executeMiddleware 方法,但最终的中间件收到了未定义的消息。追踪:final message : undefined !!! the initial message : Hello
  • @Thomas 我看到了那个评论。如果我有解决方案,我会在这里分享。但我仍然坚持这个问题。
  • @Thomas 如果您有解决方案,可以极大地帮助我。我似乎无法理解这件事。

标签: javascript node.js class middleware


【解决方案1】:

对于那些正在寻找工作示例的人。

// MIDDLEWARE CLASS
"use strict";
let info = { msg: '' };

class Middleware {
    constructor() {
        this.middlewares = [];
    }

    use(fn) {
        this.middlewares.push(fn);
    }

    executeMiddleware(middlewares, data, next) {
        const composition = middlewares.reduceRight((next, fn) => v => {
            // collect next data
            info = data;
            fn(info, next)
        }, next);       
        composition(data);
    }

    run(data) {
        this.executeMiddleware(this.middlewares, data, (info, next) => {
            console.log(data);
        });
    }
}
module.exports = Middleware;

使用示例:

// index.js
const Middleware = require('./Middleware');
const middleware = new Middleware();

middleware.use(function(info, next) {
    info.msg += ' World';
    next();
});

middleware.use(function(info, next) {
    info.msg += ' !!!';
    next();
});

// Run the middleware with initial value
middleware.run({msg: 'Hello'});

【讨论】:

    【解决方案2】:

    接受的答案有一些问题,即未使用/不需要的变量。我也想发布一个替代答案,因为这就是 stackexchange 的用途。

    用法示例同理

    class Middleware {
      constructor() {
        this.middlewares = [];
      }
      use(fn) {
         this.middlewares.push(fn);
      }
      executeMiddleware(data, done) {
        this.middlewares.reduceRight((done, next) => () => next(data, done), done)
    (data);
      }
      run(data) {
        this.executeMiddleware(data, done => console.log(data));
      }
    }
    

    【讨论】:

    • 单个 api 资源/端点的使用示例怎么样?例如,如果我在 api“控制器”中有 5 个资源,我只想将某些中间件逻辑应用于 5 个资源中的 2 个。对于基于函数的中间件,我会使用类似:app.post('/item', middlewareOnlyForThisResource, (req, res, next) => ...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 2022-07-29
    • 2014-07-05
    • 2019-07-09
    • 1970-01-01
    • 2016-07-02
    相关资源
    最近更新 更多