Не считывается переменная из constructor

В expressjs используется промежуточный слой для обработки входях вызовов через класс /middlewares/index.js

class Middlewares {
  constructor(options) {
    this.options = options;
  }

  general(req, res, next) {
    console.log(this.options)
  }

  test() {
    console.log(this.options)
  }
}

export default Middlewares;

В app.js

import express from 'express';
import { createServer } from 'http';
import Middlewares from './middlewares/index.js'

const app = express();

const options = {
  whiteListSite: ['http://localhost:81', 'http://localhost:83'],
};

const server = createServer(app);
const middlewares = new Middlewares(options);

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(middlewares.general); //<-- получаю ошибку TypeError: Cannot read properties of undefined (reading 'options')

middlewares.test() //<-- здесь срабатывает все, в консоль выводиться { whiteListSite: [ 'http://localhost:81', 'http://localhost:83' ] }

app.get('/', function(req, res) {
  res.send('hello world');
});

server.listen(8080, () => {
  console.log(`GateWay app listening on port ${8080}`);
});

В ходе работы сервера, когда срабатывает обработчик т.е при любом запросе по роутам, в функции general выдаётся ошибка TypeError: Cannot read properties of undefined (reading 'options'), но когда вызываю test() все хорошо работает без сбоев

Т.е функция из класса не может получить переменную из конструктора класса. С чем это связано?


Ответы (1 шт):

Автор решения: SwaD

Ошибка связана с потерей контекста вызова
Так же вы забыли вызвать функцию next(), которая активирует следующую функцию промежуточной обработки в приложении.

Для устранения ошибки, предложу пару способов

Первый, использовать замыкания и передавать this в отдельной переменной

general() {
  const self = this // Присваиваем this отдельной переменной
  // Возвращаем новую функцию
  return function (req, res, next) {
    console.log(self.options)
    next()
  }
}

/* остальной код */

// Передаем результат работы метода general
app.use(middlewares.general())

Второй, использовать стрелочную функцию, т.к. они не обладают собственным контекстом

general = (req, res, next) => {
  console.log(this.options)
  next()
}

/* остальной код */

// Передаем сам метод general
app.use(middlewares.general)

Можно конечно еще привязать в явном виде контекст к вашему варианту метода general

app.use(middlewares.general.bind(middlewares))

однако мне этот способ не очень нравится

→ Ссылка