node.js - 使用路由、 Controller 和模型重构 NodeJS 项目的中间件代码

标签 node.js mongodb optimization refactoring project-structure

我目前在构建 NodeJS 项目时遇到困难。我关注了几个 YouTube 系列,看到人们使用不同的技术来构建他们的代码。对于我的情况,您建议我采用哪种结构?最佳实践是什么?

我有我的 app.js,其中包含与 MongoDB 的连接建立、初始化express、bodyParser、pug 作为 View 引擎,最后启动服务器。

我的 router.js 包含所有路由,不幸的是还包含一些中间件代码,我想将其移至它们自己的专用 Controller 中。

models 文件夹包含 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

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

1. 当请求主页时,它会找到所有人员,然后找到 MongoDB 中的所有殡葬师,最后渲染页面。我可以想象,这不是最佳实践,但如何重构它?

// 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 ,并且没有真正简化事情:

// 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 添加一个新文档。我该如何做到这一点而不必重写相同的行?

最佳答案

有两件事,当组合使用时,会让代码变得更好:

  • Collection.find 返回一个 Promise
  • 要在现代 Javascript 中等待 Promise 解析,请使用 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:

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
  }
});

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

关于node.js - 使用路由、 Controller 和模型重构 NodeJS 项目的中间件代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61726347/

相关文章:

node.js - 从 s3 文件中读取范围之间的行

javascript - 无法监视现有功能

java - 使用 Java 驱动程序获取 Mongo 实例的版本

mongodb 副本集成员无法通过 SSL 加入集群

c# - 如何最好地优化这一小段 C# Linq 代码

javascript - 为什么我无法访问 LDAP 的所有属性?

node.js - 内置node.js模块的代码

arrays - 将 'array of objects' 映射到一个简单的键值数组

php - 优化数据库设计中的表

c# - 不必要的大括号会降低性能吗?