首页 > 解决方案 > TypeScript:“外包”方法。干净的方式

问题描述

我目前正在研究一个我在 express 中用作中间件的类。在我进入课堂之前,请记住,稍后我将通过首先创建我的类“Authenticator”的实例然后注入它的方法来注入中间件

app.use(authInst.express)

所以关键点将是这个函数的执行上下文(this)。这是我到目前为止的代码

备选方案 1

class Authenticator {
    opts:IAuthOpts ;
    express: RequestHandler| ErrorRequestHandler

    constructor(opts:IAuthOpts){
        this.opts = opts;
        this.express = function(req:Request, res:Response, next:NextFunction){

            if(this.opts.enabled) {
                mainController(req, res, next, this.opts)
            } else {
                next();
            }
        }
    }
}

这是有效的。但是我不想在构造函数中编写函数,因为我发现它的代码非常丑陋。像这样将express方法直接放在类中

不工作

class Authenticator {
    opts:IAuthOpts;

    constructor(opts:IAuthOpts){
        this.opts = opts;
    }

    express(req, res, next){
        if(this.opts.enabled) {
            mainController(req, res, next, this.opts)
        } else {
            next();
        }    
    }
}

将不起作用,因为 express 的执行上下文会给我这个未定义的。所以剩下的就是使用这种替代方法

备选方案 2

class Authenticator {
    opts:IAuthOpts ;
    express: RequestHandler| ErrorRequestHandler

    constructor(opts:IAuthOpts){
        this.opts = opts;
        this.express = _express.bind(this);
    }

    private _express(req, res, next){
        if(this.opts.enabled) {
            mainController(req, res, next, this.opts)
        } else {
            next();
        }    
    }
}

现在这也有效,并且是迄今为止我对这个问题的首选解决方案,因为将方法外包给另一个文件并保持我的文件很小也很容易。缺点是绑定。我不是 bind 的忠实拥护者,因为如果我使用相同的参数调用它们,无论从哪里调用它们,我都希望我的函数返回相同的值,在这种情况下,您总是需要将类绑定到它。

是否有更好的解决方案可以从 TypeScript 类中外包一个方法,并且仍然不必使用 bind 注入执行上下文?

标签: typescriptclassexpressthisexecutioncontext

解决方案


您可以使用箭头函数代替绑定:

class Authenticator {
    opts:IAuthOpts ;

    constructor(opts:IAuthOpts){
        this.opts = opts;
    }

    express = (req, res, next) => {
        if(this.opts.enabled) {
            mainController(req, res, next, this.opts)
        } else {
            next();
        }    
    }
}

如果您想将实现移动到另一个文件,最清楚的方法可能是定义一个函数,该函数将, 和,Authenticator一起作为普通参数req,然后从箭头函数中调用该函数:resnext

class Authenticator {
    opts:IAuthOpts ;

    constructor(opts:IAuthOpts){
        this.opts = opts;
    }

    express = (req, res, next) => otherFunction(this, req, res, next);
}

// In other file
function otherFunction(authenticator: Authenticator, req: Request, res: Response, next: NextFunction) { 
    if(authenticator.opts.enabled) {
        mainController(req, res, next, authenticator.opts)
    } else {
        next();
    }    
}

如果这不是您想要的,请澄清问题。


推荐阅读