比如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) {
...
}
如果还有其他页面也要展示无人回复的话题,那岂不是要在查一次?
有什么办法把这个方法提取出来吗?哪地方用到了,直接调用就可以了!!
内存 -> 缓存 -> 数据库 你可以根据数据访问的频繁程度选取存储的位置.
@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 可是如果有很多页面都用到了,都写一样的代码去查,万一要改一个字段或者变一下逻辑,岂不是很麻烦
比如注册用户,就写这样的代码
// controllers/reg.js
export = function (username, password, callback) { … callback(…) }
@coderfox 我明白了,这样就可以满足了,万分感谢