Контекст : я тестирую простую модель в базу данных и из нее. Не настоящий тест, это предшественник некоторых интеграционных тестов. Используя Sequelize и findOne
.
Проблема . Прямые данные возвращенного экземпляра модели, т.е. email.ulid, email.address, email.isVerified, не определены.
Мой вопрос . Почему они не определены?
Sequelize: 5.15.0
Typescript: 3.5.3
mysql Ver 15.1 Distrib 10.4.6-MariaDB
Запись в базу данных .
await testingDatabase.sync({
force: true
}).then(async () => {
await Email.create({
ulid: the_ulid.bytes,
address: "dave@world.com",
isVerified: false
})
})
Получить запись обратно.
await Email.findOne({
where: {
address: "dave@world.com"
}
, rejectOnEmpty: true //to shut typescript up
}).then( emailData => {
console.log("Email: ", email)
})
Console.log экземпляра email
:
Email: Email {
dataValues: {
ulid: <Buffer 01 6c a3 36 11 9c 1e 9b a6 ce 60 b7 33 3e e7 21>,
address: 'dave@world.com',
isVerified: false,
deletedAt: null,
createdAt: 2019-08-18T05:32:05.000Z,
updatedAt: 2019-08-18T05:32:05.000Z
},
...,
isNewRecord: false,
ulid: undefined,
address: undefined,
isVerified: undefined,
createdAt: undefined,
updatedAt: undefined,
deletedAt: undefined
}
^^^ Как ясно, сразу выше, все прямые атрибуты в экземпляре равны нулю.
Следующее работает , но с побочным эффектом, который isVerified
возвращается как 0
, а не false
, и впоследствии не дает прямого сравнения с исходными данными. Кроме того, я теряю другие функциональные возможности экземпляра модели, которые пригодятся в более сложных моделях:
Email.findOne({
where: { address: "dave@world.com" }
, raw: true
, rejectOnEmpty: true
})
Они также работают , но в результате Typescript жалуется на то, что возвращенный объект не имеет свойств, к которым я затем обращаюсь (хотя они существуют и тест работает):
.then( emailData => {
console.log("All getters: ", emailData.get())
// AND
console.log("All getters(plain): ", emailData.get({plain: true}))
// AND
console.log("toJSON: ", emailData.toJSON())
})
Этот следующий (предложенный Vivek) работает, если доступны данные, но JSON.parse не может правильно обработать буфер:
const dataOnly = JSON.parse(JSON.stringify(emailData))
Другие жаловались (SE answer), что console.log каким-то образом опечатывает экземпляр, но при любом другом доступе к этим свойствам они все еще не определено.
2 ответа
Решение:
Проблема была с плагином Babel
.
Настройка моделей Sequelize в соответствии с документацией Sequelize / Typescript определяет свойства класса для каждой модели представляющие модельные поля.
Плагин Babel:
"@babel/proposal-class-properties"
В:
plugins: [
"@babel/proposal-class-properties"
, ...
]
Преобразует эти свойства класса в вызовы defineProperty()
объекта модели Class, вызываемые по очереди помощником _defineProperty()
:
_defineProperty(this, "yourFieldName", void 0);
Это инициализирует свойство объекта со значением undefined
.
Очевидно, что когда findOne
впоследствии попытался обновить модель, он отказался перезаписать эти существующие свойства в модели.
Вот, пожалуйста, вы можете попробовать просто JSON.parse
и JSON.stringify
;
Email.findOne({
where: {
address: "dave@world.com"
}
}).then( emailData => {
const dataOnly = JSON.parse(JSON.stringify(emailData));
console.log(dataOnly); // <--- YOUR DATA
console.log(emailData); // <--- YOUR INSTANCE
})
«Typescript жалуется, что у возвращенного объекта нет свойств, к которым я затем обращаюсь»
.then( emailData => {
console.log("All getters: ", emailData.get())
// AND
console.log("All getters(plain): ", emailData.get({plain: true}))
return emailData.get({plain: true}); // <-- I think you forgot to return this
});
Я думаю, что ошибка в том, что вы не можете вернуть результат обратно. Проверьте приведенный выше код.
Похожие вопросы
Связанные вопросы
Новые вопросы
node.js
Node.js — это основанная на событиях, неблокирующая, асинхронная среда выполнения ввода-вывода, использующая движок Google V8 JavaScript и библиотеку libuv. Он используется для разработки приложений, которые интенсивно используют возможность запуска JavaScript как на стороне клиента, так и на стороне сервера и, следовательно, выигрывают от возможности повторного использования кода и отсутствия переключения контекста.