NodeJS Необработанный отказ от обещания

1

У меня есть метод 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'

Теги:
google-app-engine

2 ответа

2
Лучший ответ

Прежде всего, я бы сказал, что динамическое require - это способ попасть в беду. Позвольте мне структурировать свой ответ в двух частях, чтобы подчеркнуть причины, по которым его следует избегать, и предлагать несколько решений вместо этого.


Основные проблемы

  1. Синхронная загрузка во время выполнения

    require - это синхронная операция, и, как мы все знаем, такие операции блокируют Event Loop. Представьте себе относительно огромное количество пользователей, потребляющих ваше приложение одновременно, и задержку цикла, которая сказывается выше разумных значений или, по крайней мере, начинает вызывать проблемы с производительностью.

  2. Трудно тестировать такие динамические модули

    Как вы можете гарантировать, что ваше приложение достаточно стабильно, без надлежащего тестирования? С динамическим требованием это становится нетривиальной задачей. Это приводит к другому вопросу - действительно ли у вас такое количество моделей данных, которые они должны быть созданы и загружены динамически? А если нет, вы можете сделать вашу работу намного более комфортной с четко определенными и явно требуемыми моделями данных, а не "магической" загрузкой, подверженной ошибкам. А также не забывайте о круговых зависимостях и других ужасающих мерзостях, которые будут молчать до момента импорта.

  3. Общий дизайн такого приложения

    Стоит прочитать тему 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 для обработки отказов.

0

Это всего лишь небольшой подход к тому, как можно это решить, но могут быть некоторые более эффективные подходы. Почему бы вам не попытаться найти инструкцию 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: Это не должно показывать передовую обработку ошибок, просто написал это в моем кофе-брейке.

  • 1
    Спасибо, я попробовал это, но я получаю тот же отказ от необработанного обещания, и теперь появляется новая ошибка "cb is not function". (узел: 4962) UnhandledPromiseRejectionWarning: необработанное отклонение обещания (идентификатор отклонения: 1): TypeError: cb не является функцией (узел: 4962) [DEP0018] DeprecationWarning: Необработанное отклонение обещания не рекомендуется. В будущем отклонения обещаний, которые не обрабатываются, завершат процесс Node.js с ненулевым кодом завершения.
  • 0
    Обратите внимание, что я расширил подпись до getModel (kind, cb ). Вы добавили это в свой код? И где вы используете обещания? Я немного озадачен тем, что вы возвращаете отклонение обещания в требовании.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню