TypeScript:“外包”方法。干净的方法

时间:2018-10-22 15:01:38

标签: typescript class express this executioncontext

我目前正在研究一个用作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的执行上下文会将其定义为undefined。所以剩下的就是使用这种替代方法

替代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注入执行上下文?

1 个答案:

答案 0 :(得分:2)

代替绑定,您可以使用箭头功能:

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作为普通参数以及reqres,和next,然后从箭头函数调用该函数:

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();
    }    
}

如果这不是您想要的,请说明问题。