Nodejs, экспресс-маршруты как классы es6
Я хочу немного очистить свой проект, и теперь я пытаюсь использовать классы es6 для своих маршрутов. Моя проблема в том, что этот всегда undefined.
var express = require('express');
var app = express();
class Routes {
constructor(){
this.foo = 10
}
Root(req, res, next){
res.json({foo: this.foo}); // TypeError: Cannot read property 'foo' of undefined
}
}
var routes = new Routes();
app.get('/', routes.Root);
app.listen(8080);
Ответы
Ответ 1
попробуйте использовать код для вывода this
:
app.get('/', routes.Root.bind(routes));
Вы можете выйти из шаблона с помощью подчеркивания bindAll. Например:
var _ = require('underscore');
// ..
var routes = new Routes();
_.bindAll(routes)
app.get('/', routes.Root);
Я также обнаружил, что es7 позволяет вам писать код более элегантным способом:
class Routes {
constructor(){
this.foo = 10
}
Root = (req, res, next) => {
res.json({foo: this.foo});
}
}
var routes = new Routes();
app.get('/', routes.Root);
Ответ 2
Это происходит потому, что вы передали метод как отдельную функцию для выражения. Express не знает ничего о классе, из которого он исходит, поэтому он не знает, какое значение использовать как this
при вызове метода.
Вы можете заставить значение this
с bind
.
app.get('/', routes.Root.bind(routes));
Или вы можете использовать альтернативную конструкцию для управления маршрутами. Вы все еще можете использовать множество синтаксических преимуществ для объектно-ориентированного программирования без классов.
function Routes() {
const foo = 10;
return {
Root(req, res, next) {
res.json({ foo });
}
};
}
const routes = Routes();
app.get('/', routes.Root);
app.listen(8080);
- Вам не придется беспокоиться о значении
this
- Не имеет значения, вызывается ли функция с помощью
new
или нет
- Вы можете избежать сложности вызова
bind
на каждом маршруте
Там есть хороший список ресурсов здесь, о том, почему классы ES6 не так хороши, как могут показаться.
Ответ 3
Вышеуказанные ответы кажутся немного сложными. Оформите, что я здесь сделал:
class Routes {
constructor(req, res, next) {
this.req = req;
this.res = res;
this.next = next;
this.foo = "BAR"
// Add more data to this. here if you like
}
findAll (){
const {data, res,} = this; // Or just reference the objects directly with 'this'
// Call functions, do whaterver here...
// Once you have the right data you can use the res obejct to pass it back down
res.json ({foo: this.foo}); // Grabs the foo value from the constructor
}
}
Теперь, когда дело доходит до использования этого класса, вы можете сделать что-то в этом роде:
var express = require('express');
var router = express.Router();
var {Routes} = require('./Routes');
router.get('/foo', (req, res, next) => {
new Routes(req, res, next).findAll();
});
Я бы разделил два файла, так что вам просто нужен класс Routes
в вашем файле Router
.
Надеюсь, это помогло!
Ответ 4
Или, если вам не нравится привязывать контекст к маршрутам, вы можете привязать его к методам в самом конструкторе вашего класса.
например:
constructor() {
this.foo = 10;
this.Root = this.Root.bind(this);
}