如何在Node.js中实现AOP?

8
我是一名有用的助手,可以进行文本翻译。
我有一个小问题,在使用node.js进行AOP方面。假设我有一个名为server.js的脚本应用程序,并且我想监视其函数。
以下是代码:
var express = require('express');

var app = express();

app.get('/', function(req, res){
    res.setHeader('Content-Type', 'text/plain');
    res.end('Home');
});

app.get('/login', function(req, res){
    login(req,res);
    module.exports.login_(req, res);
});
app.use(function(req, res, next){
    res.setHeader('Content-Type', 'text/plain');
    res.send(404, 'Page introuvable !');
});

function login(req, res){
    res.setHeader('Content-Type', 'text/plain');
    res.end('Page de login');
}

app.listen(1616);

如您所见,我想监视唯一的函数login(req,res)。 为了做到这一点,我想在另一个脚本中使用AOP,但是我能找到的所有内容 - 我认为这是由于JavaScript语言的特性 - 都涉及大量代码干扰。

是否有任何方法可以像Spring / Java一样进行AOP?而不必进行任何代码干扰吗?

目前,我的解决方案是:
这是我们的应用程序,其中包含一些代码干扰

    var express = require('express');

    var app = express();

    app.get('/', function(req, res){
        res.setHeader('Content-Type', 'text/plain');
        res.end('Home');
    });

    app.get('/login', function(req, res){

        //We need to use the function in module.exports
                    //--> code intrusion
        //login(req,res);
        module.exports.login_(req, res);
    });


    app.use(function(req, res, next){
        res.setHeader('Content-Type', 'text/plain');
        res.send(404, 'Page introuvable !');
    });


    function login(req, res){
        res.setHeader('Content-Type', 'text/plain');
        res.end('Page de login');
    }

    //We wrap here the function we want to monitor
    wrappedLogin = function(req, res){
        login(req, res);
    }

    module.exports = {
        login_ : wrappedLogin
    };


    app.listen(1616);

这是我们的AOP脚本

var aop = require("node-aop");

//Include the server
var server = require('./server.js');


aop.before(server, "login_", function(key, value){
        //I do some stuff here
});


aop.after(server, "login_", function(key, value){
        //I do some stuff here
});

最后,我所要做的就是
node aop.js

它能够工作,但是你可以看到,有一些代码干扰。我想摆脱它。有没有人有什么想法?

4个回答

8

我认为这是Javascript语言本质的问题-需要大量代码插入。

请不要 :'(

AOP是OOP的扩展,没有OOP就没有AOP。

我建议您使用kaop或带有ES7装饰器的TS版本kaop-ts

1º: npm install kaop --save

2º:定义一个通知来监视您的方法:

import { reflect } from "kaop"

const Log = reflect.advice(meta => {
  //meta.args contains the arguments {array}
   console.log(meta.methodName + " called");
   console.log("with arguments: " + meta.args);
   console.log("returned: " + meta.result);
})

3º 你需要按照面向对象编程的指导方针组织你的代码:

const Controller = createClass({
  constructor: function(app){
    app.get('/', this.home);
    app.get('/login', this.login);
    app.use(this.notFound);
  },
  login: [function(req, res){
    //what ever
  }, Log],
  home: [function(req, res){
    res.setHeader('Content-Type', 'text/plain');
    res.end('Home');
  }, Log],
  notFound: [function(req, res){
    res.setHeader('Content-Type', 'text/plain');
    res.send(404, 'Page introuvable !');
  }, Log]
})

我在2018年写了一篇文章,讨论了JS服务器端上的AOP。


这对于像(function(){var Foo = function(args) {/*...*/};Foo.prototype.bar = function(args){/*...*/};exports.Foo = Foo;})();这样编写的JavaScript文件也适用吗?这是当前我正在查看的代码库的构造方式,我无法更改它。我还对如何将其记录到文件中感兴趣,因为 - 我想我们都同意 - 在Node.js中记录具有父对象引用的对象时,记录到控制台不是一件愉快的事情... - Nils Lindemann
我猜你可以扩展 https://github.com/k1r0s/kaop/#get-started - k1r0s

4
为了避免重复发明轮子,您可以使用nestjs这个框架,它提供了很多工具。其中,拦截器就能够实现您想要的功能(我认为)。 https://nestjs.com/

2
一个天真的尝试可能看起来像这样。
var before = function(object, functionName, action) {
  var oldFunction = object.functionName;
  var newFunction = function() {
    action();
    oldFunction();
  };
  object.functionName = oldFunction;
}

var after = function(object, functionName, action) {
  var fn = object.functionName;
  var after = function() {
    fn();
    action();
  };
  object.functionName = oldFunction;
}

JS非常灵活,你可以轻松地通过存储后续和前置操作并根据需要添加/删除它们来改进它,但至少这应该可以满足您的需求(尽管不太好)。


我实际上找到了一个解决方案(非常基础)。你可以在这里找到它:node-bakery - nugetchar

0
我是@aspectjs的维护者。最近我创建了这个库,通过ES装饰器的帮助来实现AOP,受到了Java库AspectJ的启发。
我用一个@Log()装饰器进行了测试,它正好可以做到你想要的效果。 我知道这个话题有点老了,但对其他人可能会有用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接