express开发网站,怎么将公用方法提取出来,给用到的路由调用?
发布于 8 年前 作者 tomoya92 5132 次浏览 来自 问答

比如nodeclub里的首页,路由是site.js里的index方法,代码如下

exports.index = function (req, res, next) {
  var page = parseInt(req.query.page, 10) || 1;
  page = page > 0 ? page : 1;
  var tab = req.query.tab || 'all';

  var proxy = new eventproxy();
  proxy.fail(next);

  // 取主题
  var query = {};
  if (tab && tab !== 'all') {
    if (tab === 'good') {
      query.good = true;
    } else {
      query.tab = tab;
    }
  }

  var limit = config.list_topic_count;
  var options = { skip: (page - 1) * limit, limit: limit, sort: '-top -last_reply_at'};

  Topic.getTopicsByQuery(query, options, proxy.done('topics', function (topics) {
    return topics;
  }));

  // 取排行榜上的用户
  cache.get('tops', proxy.done(function (tops) {
    if (tops) {
      proxy.emit('tops', tops);
    } else {
      User.getUsersByQuery(
        {is_block: false},
        { limit: 10, sort: '-score'},
        proxy.done('tops', function (tops) {
          cache.set('tops', tops, 60 * 1);
          return tops;
        })
      );
    }
  }));
  // END 取排行榜上的用户

  // 取0回复的主题
  cache.get('no_reply_topics', proxy.done(function (no_reply_topics) {
    if (no_reply_topics) {
      proxy.emit('no_reply_topics', no_reply_topics);
    } else {
      Topic.getTopicsByQuery(
        { reply_count: 0, tab: {$ne: 'job'}},
        { limit: 5, sort: '-create_at'},
        proxy.done('no_reply_topics', function (no_reply_topics) {
          cache.set('no_reply_topics', no_reply_topics, 60 * 1);
          return no_reply_topics;
        }));
    }
  }));
  // END 取0回复的主题

  // 取分页数据
  var pagesCacheKey = JSON.stringify(query) + 'pages';
  cache.get(pagesCacheKey, proxy.done(function (pages) {
    if (pages) {
      proxy.emit('pages', pages);
    } else {
      Topic.getCountByQuery(query, proxy.done(function (all_topics_count) {
        var pages = Math.ceil(all_topics_count / limit);
        cache.set(pagesCacheKey, pages, 60 * 1);
        proxy.emit('pages', pages);
      }));
    }
  }));
  // END 取分页数据

  var tabName = renderHelper.tabName(tab);
  proxy.all('topics', 'tops', 'no_reply_topics', 'pages',
    function (topics, tops, no_reply_topics, pages) {
      res.render('index', {
        topics: topics,
        current_page: page,
        list_topic_count: limit,
        tops: tops,
        no_reply_topics: no_reply_topics,
        pages: pages,
        tabs: config.tabs,
        tab: tab,
        pageTitle: tabName && (tabName + '版块'),
      });
    });
};

话题详情路由代码:

exports.index = function (req, res, next) {
  function isUped(user, reply) {
    if (!reply.ups) {
      return false;
    }
    return reply.ups.indexOf(user._id) !== -1;
  }

  var topic_id = req.params.tid;
  var currentUser = req.session.user;

  if (topic_id.length !== 24) {
    return res.render404('此话题不存在或已被删除。');
  }
  var events = ['topic', 'other_topics', 'no_reply_topics', 'is_collect'];
  var ep = EventProxy.create(events,
    function (topic, other_topics, no_reply_topics, is_collect) {
    res.render('topic/index', {
      topic: topic,
      author_other_topics: other_topics,
      no_reply_topics: no_reply_topics,
      is_uped: isUped,
      is_collect: is_collect,
    });
  });

  ep.fail(next);

  Topic.getFullTopic(topic_id, ep.done(function (message, topic, author, replies) {
    if (message) {
      logger.error('getFullTopic error topic_id: ' + topic_id)
      return res.renderError(message);
    }

    topic.visit_count += 1;
    topic.save();

    topic.author  = author;
    topic.replies = replies;

    // 点赞数排名第三的回答,它的点赞数就是阈值
    topic.reply_up_threshold = (function () {
      var allUpCount = replies.map(function (reply) {
        return reply.ups && reply.ups.length || 0;
      });
      allUpCount = _.sortBy(allUpCount, Number).reverse();

      var threshold = allUpCount[2] || 0;
      if (threshold < 3) {
        threshold = 3;
      }
      return threshold;
    })();

    ep.emit('topic', topic);

    // get other_topics
    var options = { limit: 5, sort: '-last_reply_at'};
    var query = { author_id: topic.author_id, _id: { '$nin': [ topic._id ] } };
    Topic.getTopicsByQuery(query, options, ep.done('other_topics'));

    // get no_reply_topics
    cache.get('no_reply_topics', ep.done(function (no_reply_topics) {
      if (no_reply_topics) {
        ep.emit('no_reply_topics', no_reply_topics);
      } else {
        Topic.getTopicsByQuery(
          { reply_count: 0, tab: {$ne: 'job'}},
          { limit: 5, sort: '-create_at'},
          ep.done('no_reply_topics', function (no_reply_topics) {
            cache.set('no_reply_topics', no_reply_topics, 60 * 1);
            return no_reply_topics;
          }));
      }
    }));
  }));

  if (!currentUser) {
    ep.emit('is_collect', null);
  } else {
    TopicCollect.getTopicCollect(currentUser._id, topic_id, ep.done('is_collect'))
  }
};

这两个路由都查询了无人回复的话题,供页面右边sidebar里展示的

cache.get('no_reply_topics', ep.done(function (no_reply_topics) {
  ...
}

如果还有其他页面也要展示无人回复的话题,那岂不是要在查一次?

有什么办法把这个方法提取出来吗?哪地方用到了,直接调用就可以了!!

13 回复

内存 -> 缓存 -> 数据库 你可以根据数据访问的频繁程度选取存储的位置.

@redhu 假如每次都从数据库里查,该怎么提取出来呢?求指教

虽然脚本语言 不建议深度oooooop 。但你起码稍微oop一下啊。

建立分层分模块,调度模式

提取公共方法,做法还是有的,只要在当前项目的node_modules目录中创建一个文件夹,然后添加一个package.json,按模块的规范定义好参数,将公共方法放到这里,其他项目中任何地方使用都可以直接require即可

@miss61008596 大神能解释的通俗点吗?我入nodejs学门还没多久。。或者有demo也好,谢谢啦

@hd19861028 我只是想提取一个公共模块,给当前项目使用,相当于service层,没有必要还在node_modules里创建文件夹的方式吧 而且一般项目里都是通过项目根路径下的package.json来初始化项目,安装node_modules 如果自己在 node_modules 里自己创建文件夹,也不便于管理呀!!

@liygheart 按 MVC 的模式,我个人理解是建 controller,在 router 里调用它。

来自酷炫的 CNodeMD

@coderfox 但是nodejs里都是异步的,提取出来的方法,返回值无效!!

@liygheart 你的意思是不是两个页面都要显示同样的内容,在每个渲染的地方要各调用一次?这个只能这样吧

@TakWolf 可是如果有很多页面都用到了,都写一样的代码去查,万一要改一个字段或者变一下逻辑,岂不是很麻烦

@liygheart

比如注册用户,就写这样的代码

// controllers/reg.js

export = function (username, password, callback) { … callback(…) }

@coderfox 我明白了,这样就可以满足了,万分感谢

回到顶部