【问题标题】:Unsure of how to approach Data Access Object/Layer in an Express / MongoDB Application不确定如何在 Express / MongoDB 应用程序中处理数据访问对象/层
【发布时间】:2015-06-19 11:50:01
【问题描述】:

我有一个运行 MongoDB 的 Express 应用程序。我想将我的数据库访问与服务器级别分开。但是,要获得数据库调用的结果,我似乎只能做以下两件事之一:

将 Res 作为参数传递

//server.js
...
var dbApi = require('../data/db-api.js');
...
app.get('/api/user', dbApi.getUsers(function (data) {
  res.send(data);
}));
...

//db-api.js
...
getUsers: function (callback) {
  MongoClient.connect(url, function (err, db) {
  if (err) {
    throw err;
  }

  db.collection(collections.Users)
    .find({})
    .toArray(function (error, documents) {
      db.close();
      callback(documents);
    });
  });
}
...

在 db-api.js 中假设 Express req/res 范式

//server.js
...
var dbApi = require('../data/db-api.js');
...
app.get('/api/user', dbApi.getUsers);
...

//db-api.js
...
getUsers: function (req, res) {
  MongoClient.connect(url, function (err, db) {
  if (err) {
    throw err;
  }

  db.collection(collections.Users)
    .find({})
    .toArray(function (error, documents) {
      db.close();
      res.send(documents);
    });
  });
}
...

但是,我觉得这两种方法都添加了我希望避免的隐式依赖项。我宁愿在 server.js 中独立调用 dbApi,以便它返回一个我可以在返回之前操作的结果集,即:

//server.js
...
var dbApi = require('../data/db-api.js');
...
app.get('/api/user', function (req, res) {
  var result = dbApi.getUsers();
  //do stuff with result as necessary
  res.send(result);
});
...

//db-api.js
getUsers: function () {
  MongoClient.connect(url, function (err, db) {
  if (err) {
    throw err;
  }

  db.collection(collections.Users)
    .find({})
    .toArray(function (error, documents) {
      db.close();
      return documents;
    });
  });
}

但是最后一个似乎不想工作,因为文档没有返回到服务器级别(结果未定义)。我知道这是因为我试图同步地做一些本质上是异步的事情。

所以,我想,我正在寻找有关应用架构最佳实践的任何建议,因为它与分离数据访问层有关。

【问题讨论】:

    标签: javascript node.js mongodb express architecture


    【解决方案1】:

    晚了一点,但在我看来,分歧应该是 Express 处理程序处理 HTTP 请求,而您的其他方法处理数据库。

    扩展您的原始脚本并使用回调:

    //server.js
    ...
    var dbApi = require('../data/db-api.js');
    ...
    app.get('/api/user', (req, res) => {
      try {
        dbApi.getUsers((documents) => res.send(documents))
      } catch (error) {
        // or something along those lines
        res.status(500).send({ error: error.message });
      }
    });
    ...
    
    //db-api.js
    ...
    getUsers: function () {
      MongoClient.connect(url, function (err, db) {
      if (err) {
        throw err;
      }
    
      db.collection(collections.Users)
        .find({})
        .toArray(function (error, documents) {
          db.close();
          if (error) {
            throw error;
          }
          return documents;
        });
      });
    }
    

    Sam H. 也是正确的,我会承诺/异步这样做,这样它会变得更直观,如果您不提供回调,节点上当前版本的 Mongodb 客户端将返回承诺:

    //server.js
    ...
    const dbApi = require('../data/db-api.js');
    ...
    app.get('/api/user', async (req, res) => {
      try {
        const documents = await dbApi.getUsers();
        res.send(documents)
      } catch (error) {
        // or something along those lines
        res.status(500).send({ error: error.message });
      }
    });
    ...
    
    //db-api.js
    ...
    getUsers: async function () {
      const db = await MongoClient.connect(url);
      const collection = await db.collection(collections.Users);
      const query = await collection.find({});
      const documents = await query.toArray();
      await db.close();
      return documents;
    }
    

    或者用承诺:

    //server.js
    ...
    const dbApi = require('../data/db-api.js');
    ...
    app.get('/api/user', (req, res) => {
      dbApi.getUsers()
        .then(documents => res.send(documents))
        .catch(error => res.status(500).send({ error: error.message })
    });
    ...
    
    //db-api.js
    ...
    getUsers: function () {
      return MongoClient.connect(url)
        .then(db => Promise.all([
          db,
          db.collection(collections.Users).find({}).toArray()
        ]))
        .then(([db, documents]) => Promise.all([documents, db.close()])
        .then(([documents]) => documents)
    }
    

    【讨论】:

      【解决方案2】:

      好吧,您可以使用promisified version of the mongo client,返回该值的承诺,然后使用异步/等待。例如,参见this answer

      【讨论】:

        猜你喜欢
        • 2021-10-03
        • 2017-02-15
        • 2022-01-06
        • 2017-11-03
        • 1970-01-01
        • 2011-04-19
        • 2011-02-09
        • 1970-01-01
        • 2012-01-20
        相关资源
        最近更新 更多