Nodejs, экспресс-маршруты как классы es6
Я хочу немного очистить свой проект, и теперь я пытаюсь использовать классы es6 для своих маршрутов. Моя проблема в том, что этой - это всегда неопределенное.
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);
4 ответов
попробуйте использовать код для pin 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);
это происходит потому, что вы передали метод как автономную функцию для выражения. 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 не так хороши, как может показаться.
приведенные выше ответы кажутся немного более сложными. Проверьте, что я сделал здесь:
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
класса в .
надеюсь, что это помогло!
или, если вам не нравится связывать контекст на маршруты, вы можете привязать его к методам в самом конструкторе класса.
например:
constructor() {
this.foo = 10;
this.Root = this.Root.bind(this);
}