как разбить логику на контроллер и модель в узле - PullRequest
0 голосов
/ 17 декабря 2018

Я не совсем понимаю, как правильно ломать логику на контроллерах и моделях в nodeJS при работе с бэкэнд-приложением.Предположим, у меня есть пример

Этот код находится в модели моего приложения, и логически я понимаю, что модель отвечает только за выбор из базы данных, а контроллер и все остальное должно выполняться контроллером,но я не совсем понимаю, как это сделать, и я попытался перенести часть кода на контроллер и экспортировать его, но у меня ничего не получилось (Пожалуйста, помогите, хотя бы с этим примером! Главное для меня - этопонять принцип работы с MVC в узле !!!

exports.currentPostPage = function(req, res){


db.query('SELECT * FROM `posts`', function (err, result) {
    if (err){
      console.log(err);
    }
    var post = result.filter(item => {return (item.id == req.params.id)? item: false})[0];
    if (post === undefined){
      res.render('pages/404');
    } else {
      res.render('pages/post-page', {postId: req.params.id, item: post});
    }

  });
};

1 Ответ

0 голосов
/ 17 декабря 2018

Итак, вы на правильном пути.Есть много разных способов сделать это в зависимости от предпочтений, но один шаблон, который я видел довольно часто, - это использование обратного вызова в качестве способа интеграции.Например, предположим, у вас есть файл вашей модели:

exports.getPostById = (id, cb) => {
  db.query('SELECT * FROM `posts` WHERE id=?', [id], function (err, result) {
    if (err){
      return cb(err); // or, alternatively, wrap this error in a custom error
    }
    // here, your logic is just returning whatever was returned
    return cb(null, result); 
  });
};

Примечание. Я также разрешаю БД обрабатывать поиск идентификатора, так как это, вероятно, более эффективно для больших наборов данных.Вы не сказали, какой модуль БД вы используете, но у всех хороших есть какой-то способ выполнения параметризованных запросов, поэтому используйте все, что работает с вашим драйвером БД.

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

// postController.js
const model = require('../models/postModel.js'); // or whatever you named it
exports.populatePost = (req, res, next, id) => {
  model.getPostById(id, (err, post) => {
    if (err) return next(err); // centralized error handler
    req.post = post;
    next(); 
  });
}

export.getOnePost = (req, res, next) => {
  if (req.post) {
    return res.render('pages/post-page', req.post);
  }
  // again, central error handling
  return next({ status: 404, message: 'Post not found' });
}

Я упомянул центральную обработку ошибок;Я предпочитаю это рассеянию логики обработки ошибок повсюду.Поэтому я либо делаю собственные ошибки для представления чего-либо, либо просто делаю то же самое, что и выше, где прикрепляю статус и сообщение к анонимному объекту.Либо будет работать для наших целей.Затем в файле промежуточного программного обеспечения вы можете иметь один или несколько обработчиков, самый простой из них:

// middleware/errors.js
module.exports = (err, req, res, next) => {
  console.error(err); // log it
  if (err.status) {
    return res.status(err.status).render(`errors/${err.status}`, err.message);
  } 
  return res.status(500).render('errors/500', err.message);
}

Наконец, в настройках маршрутизации вы можете сделать что-то вроде этого:

const postController = require('../controllers/postController');
const errorHandler = require('../middleware/errors.js');
const postRouter = express.Router();

postRouter.param('postId', postController.populatePost);
postRouter.get('/:postId', postController.getOnePost);
// other methods and routes

app.use('/posts', postRouter)

// later

app.use(errorHandler);

Как отмечалось в комментариях, некоторые люди предпочитают использовать синтаксис Promise для обратных вызовов.Я лично не нахожу их , которые намного чище, если только вы не используете синтаксис async / await.Например, если ваша библиотека db поддерживает обещания, вы можете изменить код модели, чтобы он выглядел так:

exports.getPostById = async (id, cb) => {
  // again, this assumes db.query returns a Promise
  return await db.query('SELECT * FROM `posts` WHERE id=?', [id]);
}

Тогда ваш код контроллера также должен измениться, чтобы справиться с этим:

// postController.js
const model = require('../models/postModel.js'); // or whatever you named it
exports.populatePost = async (req, res, next, id) => {
  try {
    const post = await model.getPostById(id)
    req.post = post
    return next()
  } catch (err) {
    return next(err)
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...