Я пытаюсь добавить функцию в класс на своем сервере Express/Node, но постоянно получаю TypeError: req.session.user.bills[0].getFormattedDueDate is not a function
. У меня есть другие классы, чьи функции-члены работают, в том числе в том же методе, который выдает эту ошибку. Я проверил тип объектов в req.session.user.bills
, и это был object
. Проект построен с помощью Webpack и Babel.
Если я возьму все свойства из req.session.user.bills[0]
и помещу их в новый объект, то функции будут работать. Поток данных для этого объекта работает следующим образом. Имя основного файла server2.js
.
server2.js
.userDao
получает пользователя из базы данных и возвращает объект User
с массивом Bill
s. И UserDao
, и User
стоят require
d вверху server2.js
.User
в файл EJS. Именно здесь я пытаюсь использовать функцию, и она не работает.server.js
:
const User = require('babel-loader!./src/model/user.js');
const UserDao = require('babel-loader!./src/model/userDao.js');
const Bill = require('babel-loader!./src/model/bill.js');
const userDao = new UserDao(pool);
...
app.all('/bills', function(req, res) {
const temp1 = req.session.user.bills[0].getFormattedDueDate();
res.render('bills.ejs', {
URL: config.URL,
user: req.session.user
})
});
Но если я создаю новый объект, он работает:
app.all('/bills', function(req, res) {
const temp = new Bill(
req.session.user.bills[0].id,
req.session.user.bills[0].userId,
req.session.user.bills[0].periodId,
req.session.user.bills[0].accountId,
null,
req.session.user.bills[0].name,
req.session.user.bills[0].amount,
req.session.user.bills[0].autoPay,
req.session.user.bills[0].weekDay,
req.session.user.bills[0].dueDate,
req.session.user.bills[0].dueDate2,
req.session.user.bills[0].paid
);
const temp1 = temp.getFormattedDueDate();
res.render('bills.ejs', {
URL: config.URL,
user: req.session.user
})
});
userDao.js
:
//Lots of other data is put in user...
//Bills
for (let i = 0; i < rows[BILLS_INDEX].length; i++) {
user.bills.push(new Bill(
rows[BILLS_INDEX][i].id,
rows[BILLS_INDEX][i].userId,
rows[BILLS_INDEX][i].periodId,
rows[BILLS_INDEX][i].accountId,
new Tag(rows[BILLS_INDEX][i].tagId, rows[BILLS_INDEX][i].userId, rows[BILLS_INDEX][i].name),
rows[BILLS_INDEX][i].name,
rows[BILLS_INDEX][i].amount,
rows[BILLS_INDEX][i].autoPay === 1,
rows[BILLS_INDEX][i].weekDay === 1,
rows[BILLS_INDEX][i].startDate,
rows[BILLS_INDEX][i].startDate2,
rows[BILLS_INDEX][i].paid === 1
));
}
resolve(user);
user.js
:
module.exports = class User {
constructor(id, firstName, lastName, imageUrl, email, tags, items, budgetItems, piggyBanks, bills) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.imageUrl = imageUrl;
this.email = email;
this.tags = tags || new Array();
this.items = items || new Array();
this.budgetItems = budgetItems || new Array();
this.piggyBanks = piggyBanks || new Array();
this.bills = bills || new Array();
}
}
bill.js
:
const moment = require('moment');
module.exports = class Bill {
constructor(pId, pUserId, pPeriodId, pAccountId, pTag, pName, pAmount, pAutoPay, pWeekDay, pdueDate, pdueDate2, pPaid) {
this.id = pId;
this.userId = pUserId,
this.periodId = pPeriodId,
this.accountId = pAccountId,
this.tag = pTag,
this.name = pName,
this.amount = pAmount,
this.autoPay = pAutoPay,
this.weekDay = pWeekDay,
this.dueDate = pdueDate,
this.dueDate2 = pdueDate2,
this.paid = pPaid
}
getFormattedDueDate() {
return moment(this.dueDate).format('MMM DD, YYYY');
}
getFormattedDueDate2() {
return moment(this.dueDate2).format('MMM DD, YYYY');
}
}
Я ожидал, что метод сработает, так как методы в userDao.js
работают, но я получаю ошибку неопределенного метода.
Обновлено: Я проверил req.session.user.bills[0] instanceof Bill
и вернул ложь.
Как вы ставите req.session.user.bills
в сессии? Это не похоже на Bill
объект. Вы используете JSON.stringify
-> JSON.parse
?
Я делаю это в server2.js
, когда создаю экземпляр переменной temp1
.
Когда пользователь входит в систему, я устанавливаю req.session.user = user
после получения всей его информации.
Вы звоните getFormattedDueDate
не getFormattedDate
Вы проверили, действительно ли req.session.user.bills
содержит Bill
объекты? Как я уже сказал, не похоже. Я подозреваю, что они были сериализованы -> десериализованы, что означает, что все функции удалены.
Это была опечатка в ошибке, извините. Я отредактировал его, чтобы сделать его правильным.
Я забыл упомянуть, что проверил тип req.session.user.bills[i], и это было object
. Новый мастер вопросов меня запутал :)
Хорошо... как вы проверили тип? Потому что typeof
просто скажет вам object
для любого объекта. Вы можете проверить bills[0] instanceof Bill
, который скажет вам, является ли это счетом или нет.
А, я использовал typeof
. Я проверю instanceof
.
Он вернул ложь.
Как использовать методы без повторного создания сотни объектов в req.session.user
?
Когда вы сохраняете объект в session
, он сериализуется как JSON. И когда вы его извлекаете, он снова анализируется как простой объект. Таким образом, любая исходная информация о прототипе теряется в этом процессе. Как указано в документации модуль экспресс-сессии:
To store or access session data, simply use the request property
req.session
, which is (generally) serialized as JSON by the store [...]
Чтобы восстановить информацию о прототипе, вы можете сделать:
req.session.user.bills.forEach(bill => Object.setPrototypeOf(bill, Bill.prototype));
И тогда это должно работать:
const temp1 = req.session.user.bills[0].getFormattedDueDate();
В качестве альтернативы, если вы просто хотите иметь возможность вызвать метод один раз, вы можете использовать .call
:
const temp1 = Bill.prototype.getFormattedDueDate.call(req.session.user.bills[0]);
Ты никогда не звонишь
getFormattedDate