route类无法访问本地函数#typescript #express

时间:2017-08-19 08:36:21

标签: javascript typescript express

在下面的代码中,我得到了#undefined' “loglogMePleasePlease'错误功能

有人可以帮我解决这个问题。

  

TypeError:无法读取属性' logMePleasePlease'未定义的

我大惊小怪,这种错误让我质疑一切我到目前为止编码。

import {Router, Request, Response, NextFunction} from 'express';
import * as fs from 'fs';
import { db } from '../db/lowDb'

export class employeeRoute {
    router: Router
    constructor() {
        this.router = Router();
        this.init();
    }
    init() {
        this.router.get('/', this.default);
        this.logMePleasePlease('SFDSFSDF');/*This call works fine!*/
    }
    public logMePleasePlease(err){
        console.log(err);
    }
    public default(req: Request, res: Response, next: NextFunction) {
        /*****Error when execution gets to follwing line:
        TypeError: Cannot read property 'logMePleasePlease' of undefined
        ******/
        this.logMePleasePlease('asdad');
        res.send({
            status:'ok',
            message:'employee api home'
        });
    }
}
const employee = new employeeRoute();
export default employee.router;

3 个答案:

答案 0 :(得分:0)

这可能是因为你的路由器弄乱了函数的上下文'默认'这就是为什么这等于未定义。

您可以尝试将func绑定到构造函数中的右上下文:

this.default.bind(this)

但这很麻烦。你确定为每条路线都有一个单独的路由器吗?我将创建唯一的路由器并将其提供给构造函数中的每个路由类..

我在创建从一个流行教程中获取的路由时使用了以下模式,由于大量使用静态方法,这有点争论,但对我来说效果很好:

import { NextFunction, Request, Response, Router } from 'express'


export class IndexRoute {


    static CREATE(router: Router) {
        console.log('[IndexRoute::create] Creating route /');

        router.get('/', (req, res, next) => {
            new IndexRoute().index(req, res, next)
        })
    }


    index(req: Request, res: Response, next: NextFunction) {
        console.log('[IndexRoute::index]');
        const data = { status: 'ok' };
        res.status(200).json(data);
    }

}

答案 1 :(得分:0)

这是由JavaScript在调用函数时绑定this的方式引起的。

让我们举几个例子说明我的意思以及如何修复它。

class BindingTest {
  func() {
    console.log(this)
  }
}

const test = BindingTest()
const testFunc = test.func

现在,正如您在此示例中所看到的,我们有test对象提供func方法,以及testFunc变量,该变量包含对该方法的引用。

重要的是要记住JavaScript移动值的方式(并向函数添加函数),特别是一切都是值。在这种情况下,当我们分配const testFunc = test.func时,我们正在做的是获取BindingTest.prototype.func值(我们在类上定义的函数)并直接引用它。

因此,当我们运行以下内容时:

testFunc()

我们会看到它打印出undefined而不是BindingTest上下文...

这很奇怪,因为当我们运行以下内容时:

test.func()

我们打印了上下文!

正如我所提到的,这是通过对象的原型调用策略调用函数的结果(在这种情况下this绑定到test)并将函数作为隔离值调用(在这种情况下,thisundefined)。

修复实际上非常简单,JavaScript提供了.bind()方法,允许您将this上下文与函数值相关联。

const boundTestFunc = test.func.bind(test)

现在,如果我们去拨打boundTestFunc,我们就会按照我们的预期打印出BindingTest上下文。

我希望这能澄清你所看到的“为什么”背后的原因。在您的情况下:修复将只是在构造函数中使用以下代码。

this.router.get('/', this.default.bind(this));

答案 2 :(得分:0)

如果这对任何人有帮助,以下是在 use 上使用类和 Router 方法的示例代码(参见文档 here 底部的示例)。

server.ts

import { Test } from './test';
import express from "express";
import compression from "compression";

export class Server {
    private app: express.Application;
    private port: number = 3000;
    private test: Test;

    constructor() {
        // setup server
        this.app = express();
        this.app.use(express.urlencoded({ extended: true }));   // needed for POST requests
        this.app.use(express.json());   // needed for POST requests
        this.app.use(compression());

        // create classes
        this.test = new Test();

        // tell app to use routes
        this.app.use("/test", this.test.router);

        // start listening
        this.app.listen(this.port, () => {
            console.log("Node Express server listening on port " + this.port);
        });
    }

}

test.ts

import express, { Router, Request, Response } from "express";

export class Test {
    public router: Router = express.Router();
    private testVar: string = "Hello World";

    constructor() {
        this.router.get('/', [this.get.bind(this)]);
    }

    private async get(req: Request, res: Response) {
        try {
            // return
            res.status(200).send(this.testVar);
        } catch (error) {
            res.status(500).send(error);
        }
    }

}