重构NodeJS项目的中间件代码,使用路由、控制器和模型 [英] Refactoring middleware code of NodeJS project, using routes, controllers and models

查看:76
本文介绍了重构NodeJS项目的中间件代码,使用路由、控制器和模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前难以构建我的 NodeJS 项目.我关注了几个 YouTube 系列,看到人们使用不同的技术来构建他们的代码.在我的情况下,您会建议我使用哪种结构?最佳做法是什么?

I currently have difficulties to structure my NodeJS project. I followed several YouTube series, seeing people using different techniques to structure their code. Which structure would you suggest me in my case? What's best practice?

我的 app.js 包含到 MongoDB 的连接建立、初始化 express、bodyParser、pug 作为视图引擎,最后启动服务器.

I've my app.js which contains connection establishment to MongoDB, initializing express, bodyParser, pug as view engine and finally starting the server.

我的 router.js 包含所有路由和不幸的一些中间件代码,我想将它们移动到他们自己的专用控制器中.

My router.js contains all routes and unfortunately some middleware code, which I want to move into their own dedicated controller.

models 文件夹包含 MongoDB 的所有架构文件.

The models folder holds all schema files for MongoDB.

// File structure:
.
├─ controllers
|  ├─ morticians.js
|  ├─ people.js
|  └─ pickups.js
├─ models
|  ├─ mortician.js
|  ├─ person.js
|  └─ pickup.js
├─ views
|  ├─ elements
|  |  └─ ..
|  ├─ pages
|  |  ├─ dashboard.pug
|  |  └─ ..
|  └─ layout.pug
├─ app.js
└─ router.js

我们是一家医院,有时人们会死在这里.殡仪馆来接他们,但从我们的系统中删除此人的过程尚未自动化.这就是这个 webapp 的用途.从我们的数据库中提取所有死者,将他们显示在 Web 应用程序中,并在殡仪馆人员来接该人后立即将其删除.

We're a hospital an sometimes people die here. A mortician comes and picks them up, but the process to remove this person from our systems isn't automated yet. That's what this webapp is for. Pulling all deceased from our database, displaying them in the webapp and removing it as soon as the mortician came and picked that person up.

1. 当主页面被请求时,它会找到所有人,然后是来自 MongoDB 的所有殡仪馆,最后呈现页面.我可以想象,这不是最佳实践,而是如何重构它?

1. When the main-page is requested, it finds all people, then all morticians from MongoDB and finally rendering the page. I can imagine, that this not best practice, but how to refactor it?

// snippet router.js
const Person= require('./models/person')
const Mortician = require('./models/mortician')
router.get('/', (req, res, next) => {
  Person.find({ pickedUp: false }, (err, people) => {
    Mortician.find({}, (err, morticians) => {
      if (err) return console.log(err);
      res.render('pages/dashboard', {
        title: 'Dashboard',
        persons: people,
        morticians: morticians
      })
    })
  })
}

我尝试将 MongoDB 操作移动到它们的 controller 文件中,就像这样.它有效,但我不确定,因为它使用了多个 Promise 并且没有真正简化:

I tried moving the MongoDB operations into their controller files, like this. It worked, but I'm unsure since it's using multiple promises and not really simplifying things:

// snippet router.js
const ConPeople = require('./controllers/people')
const ConMorticians = require('./controllers/morticians')
router.get('/',
  (req, res, next) => {
    res.locals.options = { pickedUp: false }
    ConPeople.find(req, res, next)
      .then((people) => {
        res.locals.people = people
        next()
      })
  },
  (req, res, next) => {
    res.locals.options = {}
    ConMorticians.find(req, res, next)
      .then((morticians) => {
        res.locals.morticians = morticians
        next()
      })
  },
  (req, res) => {
    res.render('pages/dashboard', {
      title: 'Dashboard',
      people: res.locals.people,
      morticians: res.locals.morticians.reverse()
    })
  }
)

// snippet controllers/people.js
module.exports = {
  find: (req, res, next) => {
    return Person.find(res.locals.options)
  }
}

2. 在某些情况下,我需要执行命令,例如从 MongoDB 中删除或添加一个人.例如,殡仪馆来接人.我需要将那个人的状态设置为 pickedUp = true,最终添加一个新的殡仪馆(如果提供)并向集合 pickups 添加一个新文档.如何在不必重写相同行的情况下做到这一点?

2. In some cases I need to execute commands like deleting or adding a person from MongoDB. For example, a mortician comes and picks up a person. I need to set the status of that person to pickedUp = true, eventually add a new mortician if that's provided and add a new document to the collection pickups. How do I do that without having to rewrite the same lines?

推荐答案

有两个东西,当结合使用时,会使代码更好:

There are 2 things which, when used in combination, will make the code much nicer:

  • Collection.find 返回一个 Promise.
  • 要等待 Promise 在现代 Javascript 中解析,请使用 await
  • Collection.find returns a Promise.
  • To wait for a Promise to resolve in modern Javascript, use await

您可以使用以下代码:

const Person= require('./models/person')
const Mortician = require('./models/mortician')
router.get('/', async (req, res, next) => {
  try {
    const persons = await Person.find({ pickedUp: false });
    const morticians = await Mortician.find({});
    res.render('pages/dashboard', {
      title: 'Dashboard',
      persons,
      morticians,
    });
  } catch(e) {
    // handle errors
  }
});

或者,要并行而不是串行检索结果,请使用 Promise.all:

Or, to retrieve the results in parallel rather than in serial, use Promise.all:

router.get('/', async (req, res, next) => {
  try {
    const [persons, morticians] = await Promise.all([
      Person.find({ pickedUp: false }),
      Mortician.find({})
    ]);
    res.render('pages/dashboard', {
      title: 'Dashboard',
      persons,
      morticians,
    });
  } catch(e) {
    // handle errors
  }
});

每当您有多个异步调用时,您都可以使用相同类型的模式 - 不需要丑陋的括号嵌套和缩进.

You can use the same sort of pattern whenever you have multiple asynchronous calls to make - no need for ugly bracket nesting and indentation.

这篇关于重构NodeJS项目的中间件代码,使用路由、控制器和模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆