У меня есть метод getModel(kind)
который возвращает модель данных Datastore в NodeJS.
Я сделал простой тип o в getModel(kind)
и обнаружил основную проблему с нечетким обещанием.
Как я могу обновить код, чтобы поймать эти неперехваченные исключения в будущем?
Вызов getModel:
//Save the data to the database
getModel('transferrequest').create(TransferRequestNew, (err, savedData) => {
if (err) {
console.log('Transfer Request New unable to create new entity. Error message: ', err);
next(err);
return;
}
console.log('savedData: ', savedData);
res.redirect('${req.baseUrl}/history');
});
Функция getModel:
function getModel(kind) {
const model = __modelsdir+'/model-'+__databackend+kind;
return require(model);
}
Создать метод, вызываемый с getModel.create
метода getModel.create
:
function create (data, cb) {
update(null, data, cb);
}
Необработанная ошибка:
(node: 31937) UnhandledPromiseRejectionWarning: Отказ от необработанного обещания (идентификатор отказа: 1): Ошибка: не удается найти модуль '/mypath/projectname/models/model-datastoretransferrequest'
Прежде всего, я бы сказал, что динамическое require
- это способ попасть в беду. Позвольте мне структурировать свой ответ в двух частях, чтобы подчеркнуть причины, по которым его следует избегать, и предлагать несколько решений вместо этого.
Синхронная загрузка во время выполнения
require
- это синхронная операция, и, как мы все знаем, такие операции блокируют Event Loop. Представьте себе относительно огромное количество пользователей, потребляющих ваше приложение одновременно, и задержку цикла, которая сказывается выше разумных значений или, по крайней мере, начинает вызывать проблемы с производительностью.
Трудно тестировать такие динамические модули
Как вы можете гарантировать, что ваше приложение достаточно стабильно, без надлежащего тестирования? С динамическим требованием это становится нетривиальной задачей. Это приводит к другому вопросу - действительно ли у вас такое количество моделей данных, которые они должны быть созданы и загружены динамически? А если нет, вы можете сделать вашу работу намного более комфортной с четко определенными и явно требуемыми моделями данных, а не "магической" загрузкой, подверженной ошибкам. А также не забывайте о круговых зависимостях и других ужасающих мерзостях, которые будут молчать до момента импорта.
Общий дизайн такого приложения
Стоит прочитать тему ESLint для global-require
и понять, почему она не разрешена в разных наборах правил по умолчанию (например, Airbnb). Но вы на самом деле упомянули о себе:
Я сделал простой тип o в
getModel(kind)
и обнаружил основную проблему с нечетким обещанием.
Если этого достаточно, чтобы разорвать ваше приложение, можно ли считать это приложение надежным? Это то же самое, что и с сырыми строками в качестве параметров: нужно скорее сделать их константами или присутствовать в качестве самой функции, избавиться от трудно отлаживаемых ошибок времени выполнения в обмен на простые синтаксические ошибки при запуске.
Явно требуемые модели
Создавайте четко определенные структуры объектов, которые представляют структуры данных и загружают их явно из одного агрегированного файла index.js
:
// models/transfer-request.js
class TransferRequest {
create(instance, cb) {
// Implementation...
}
}
module.exports = TransferRequest;
// models/index.js
const TransferRequest = require('./transfer-request.js');
// Other models requires...
module.exports = {
TransferRequest,
// Other models exports...
};
Создайте экземпляры с помощью Factory:
Если вы все еще хотите придерживаться того, что у вас есть, создайте модель Factory с использованием стандартного шаблона:
class ModelFactory {
constructor(model){
switch(model) {
case 'transferrequest':
// Implementation of TransferRequest object creation...
break;
case 'othertransferrequest':
// Implementation of OtherTransferRequest object creation...
break;
default:
throw new Error('Unknown class');
}
}
}
Время и время лучше создавать реальные объекты модели четким и видимым способом, четко определенным в коде, чем скрывать возможные варианты с динамической загрузкой.
И да, если вы все еще хотите require
во время выполнения, просто используйте try/catch
для обработки отказов.
Это всего лишь небольшой подход к тому, как можно это решить, но могут быть некоторые более эффективные подходы. Почему бы вам не попытаться найти инструкцию require? Я тестировал это, и это отлично работало:
function getModel(kind, cb) {
var model = __dirname + kind;
try {
var requiredModel = require(model);
return cb(null, requiredModel)
}
catch (e) {
return cb(new Error("model not found!"), null);
}
}
Я тестировал это с помощью __dirname
но это не должно __dirname
.
Btw: Это не должно показывать передовую обработку ошибок, просто написал это в моем кофе-брейке.