【问题标题】:Node.js async callback factoryNode.js 异步回调工厂
【发布时间】:2013-12-15 14:27:43
【问题描述】:

我正在使用 Node.js、Express 和 MySql 开发一个 RESTful API。没有使用 ORM。

我想尽可能多地重用代码来处理资源请求。

我要实现一个回调工厂,我想听听你关于我的方法。

api.js

它是主要的应用程序文件。

'use strict';

var
  http = require('http'),
  express = require('express'),
  app = express(),

  env = app.get('env'),
  config = require('./config')[env],
  pool = require('./pool')(config.database), /* node-mysql pool */

  people = require('./routes/people')(pool); /* route handlers for people resource */

app.use(express.json());
app.use(express.urlencoded());
app.use(app.router);

app.get('/people', people.findAll); /* middleware handling request for the resource */

http.createServer(app).listen(8000);

路线/people.js

该文件包含处理/peopleresource 请求的代码。

'use strict';

module.exports = {
  var
    async = require('async'),
    CallbackFactory = require('../CallbackFactory'),
    people = {};

  people.findAll = function (req, res, next) {
    async.waterfall(
      [
        CallbackFactory.createCallback('getPoolConnection', pool),
        CallbackFactory.createCallback('lastQuery', 'SELECT * FROM person'),
        CallbackFactory.createCallback('json', res)
      ],
      CallbackFactory.getCallback('next', next);
    );
  };

  return people;
};

CallbackFactory.js

模块仅导出createCallback 方法。

createCallback 的第一个参数始终是回调名称。
其他参数特定于要创建的回调。

'use strict';

var
  factoryMethods: {
    getPoolConnection: function (pool) {
      return function (callback) {
        pool.getConnection(function (err, connection) {
          callback(err, connection);
        };
      };
    },
    lastQuery: function (sql, values) {
      return function (connection, callback) {
        connection.query(sql, values, function (err, result) {
          connection.release();
          callback(err, result);
        });
      };
    },
    json: function (res) {
      return function (result, callback) {
        res.json(result);
        callback();
      };
    },
    next: function (next) {
      return function (err) {
        if (err) {
          return next(err);
        }
      };
    },
  };

module.exports = {
  createCallback: function () {
    var
      args = Array.prototype.slice.call(arguments),
      name = args.shift();

    return factoryMethods[name].apply(null, args);
  }
};

结论

我搜索并搜索了 SO,以找到对代码重用有用的方法。
我什么也没找到。也许这不是正确/最好的方法。 你怎么看?

【问题讨论】:

  • 我认为这也是个人喜好的问题。我发现很难理解 people.findAll 实际做了什么,因为增加了抽象层(尤其是因为你的回调工厂方法非常通用)。我倾向于重用一些代码,如果它使整个代码更容易理解。
  • 好主意!实现这个我会头疼 - 我宁愿为此编写一个代码生成器,尽管我讨厌重复的代码。

标签: node.js api rest express


【解决方案1】:

我认为你在这里走错了路。回调工厂不是一种常见的模式,因为它添加了一个抽象层,而不会以任何方式降低复杂性。换一种说法,将 async.waterfall 视为已经提供了您正在寻找的抽象层。或者,如果您喜欢命名函数,我推荐 async.auto,它还会根据您指定的依赖项自动确定哪些函数可以串行和并行运行。

我建议让 async.waterfall 或 async.auto 直接调用您的函数。如果您想要更多的抽象和更少的代码,请使用像 Sequelize 这样的 ORM。但是我看到你的工厂让以后出现的其他人理解你的代码变得复杂。

【讨论】:

  • 我主要关心的是避免重复。那么,你建议我封装一个 async.waterfall 或 async.auto 吗?
  • 是的,我建议使用函数而不是工厂进行封装。我会看一下模型的 Express 或 Mocha 代码库。举个反例,以下是 Sequelize 如何实现 DAO 工厂模式:github.com/sequelize/sequelize/blob/master/lib/dao-factory.js
  • 我按照您的建议使用 ORM。我尝试了 Persistence、Sequelize 和 Bookshelf,并决定使用 Bookshelf。这是我第一次尝试的gist
猜你喜欢
  • 2017-03-20
  • 1970-01-01
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-15
  • 2012-07-15
相关资源
最近更新 更多