express开发网站,怎么将公用方法提取出来,给用到的路由调用? - CNode技术社区

express开发网站,怎么将公用方法提取出来,给用到的路由调用?
发布于 10 年前 作者 tomoya92 6350 次浏览 最后一次编辑是 9 年前 来自 问答

比如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 我明白了,这样就可以满足了,万分感谢

回到顶部

AltStyle によって変換されたページ (->オリジナル) /