Nodejs nodeclub源码中EJS的疑惑
Nodejs nodeclub源码中EJS的疑惑
这个????
首先你可以先了解下这个eventproxy
模块,
这里有篇文章http://cnodejs.org/topic/4f76cafe8a04d82a3d556a07,
或者你直接去https://github.com/JacksonTian/eventproxy这里看,
你看明白这个之后你在看这里:proxy/topic.js
文件里的代码,随便一个函数都行,比如:
/**
* 根据主题ID获取主题
* Callback:
* - err, 数据库错误
* - topic, 主题
* - tags, 标签列表
* - author, 作者
* - lastReply, 最后回复
* [@param](/user/param) {String} id 主题ID
* [@param](/user/param) {Function} callback 回调函数
*/
exports.getTopicById = function (id, callback) {
var proxy = new EventProxy(); ----------重点注意0:这里有使用啊
var events = ['topic', 'tags', 'author', 'last_reply'];
proxy.assign(events, function (topic, tags, author, last_reply) {
return callback(null, topic, tags, author, last_reply);
}).fail(callback);
Topic.findOne({_id: id}, proxy.done(function (topic) {
if (!topic) {
proxy.emit(‘topic’, null);
proxy.emit(‘tags’, []);
proxy.emit(‘author’, null); --------重点注意1:这里是空
proxy.emit(‘last_reply’, null);
return;
}
proxy.emit(‘topic’, topic);
// TODO: 可以只查tag_id这个字段的吧?
TopicTag.find({topic_id: topic._id}, proxy.done(function (topic_tags) {
var tags_id = [];
for (var i = 0; i < topic_tags.length; i++) {
tags_id.push(topic_tags[i].tag_id);
}
Tag.getTagsByIds(tags_id, proxy.done('tags'));
}));
User.getUserById(topic.author_id, proxy.done('author')); -------重点注意这里2:这里才是最重要的,如果你看懂刚才上面我推荐的,那么这里你应该就没有难度了!
if (topic.last_reply) {
Reply.getReplyById(topic.last_reply, proxy.done(function (last_reply) {
proxy.emit('last_reply', last_reply || null);
}));
} else {
proxy.emit('last_reply', null);
}
}));
};
对了,github上面这句很重要啊,别漏掉了:
ep.done('tpl');
// 等价于
function (err, content) {
if (err) {
// 一旦发生异常,一律交给error事件的handler处理
return ep.emit('error', err);
}
ep.emit('tpl', content);
}
你看明白了,你或许就知道为什么了!
Nodejs nodeclub源码中EJS的疑惑
在Nodeclub源码中,EJS
(Embedded JavaScript)模板引擎被广泛使用。本文将通过分析nodeclub
中的一个具体函数来帮助理解EJS
是如何与EventProxy
模块协同工作的。
首先了解EventProxy
模块
EventProxy
是一个非常有用的模块,用于处理异步回调的管理。它可以帮助我们避免回调地狱(callback hell),使代码更清晰、更易于维护。你可以通过以下链接进一步了解EventProxy
:
示例代码解析
接下来,我们将分析nodeclub
源码中的getTopicById
函数,该函数用于根据主题ID获取主题信息。
/**
* 根据主题ID获取主题
* Callback:
* - err, 数据库错误
* - topic, 主题
* - tags, 标签列表
* - author, 作者
* - lastReply, 最后回复
* @param {String} id 主题ID
* @param {Function} callback 回调函数
*/
exports.getTopicById = function (id, callback) {
var proxy = new EventProxy(); // 创建一个新的EventProxy实例
var events = ['topic', 'tags', 'author', 'last_reply'];
proxy.assign(events, function (topic, tags, author, last_reply) {
return callback(null, topic, tags, author, last_reply);
}).fail(callback);
Topic.findOne({_id: id}, proxy.done(function (topic) {
if (!topic) {
proxy.emit('topic', null);
proxy.emit('tags', []);
proxy.emit('author', null);
proxy.emit('last_reply', null);
return;
}
proxy.emit('topic', topic);
// 获取标签
TopicTag.find({topic_id: topic._id}, proxy.done(function (topic_tags) {
var tags_id = [];
for (var i = 0; i < topic_tags.length; i++) {
tags_id.push(topic_tags[i].tag_id);
}
Tag.getTagsByIds(tags_id, proxy.done('tags'));
}));
// 获取作者
User.getUserById(topic.author_id, proxy.done('author'));
// 获取最后回复
if (topic.last_reply) {
Reply.getReplyById(topic.last_reply, proxy.done(function (last_reply) {
proxy.emit('last_reply', last_reply || null);
}));
} else {
proxy.emit('last_reply', null);
}
}));
};
关键点解析
-
创建EventProxy实例:
var proxy = new EventProxy();
这里创建了一个新的
EventProxy
实例,用于管理后续的异步操作。 -
定义需要监听的事件:
var events = ['topic', 'tags', 'author', 'last_reply'];
这里定义了我们需要监听的事件名称。
-
设置事件处理逻辑:
proxy.assign(events, function (topic, tags, author, last_reply) { return callback(null, topic, tags, author, last_reply); }).fail(callback);
assign
方法用于指定当所有指定的事件都被触发时,执行的回调函数。如果其中任何一个事件未触发,则会调用fail
方法中的回调函数。 -
查询数据库并触发事件:
Topic.findOne({_id: id}, proxy.done(function (topic) { // ... }));
使用
findOne
方法查询主题信息,并通过proxy.done
方法将结果传递给下一个处理步骤。 -
异步处理其他信息:
TopicTag.find({topic_id: topic._id}, proxy.done(function (topic_tags) { // ... })); User.getUserById(topic.author_id, proxy.done('author'));
查询标签信息和作者信息,并通过
proxy.done
方法将结果传递给下一个处理步骤。
通过以上代码和注释,我们可以看到EventProxy
如何有效地管理异步操作,确保所有数据都准备好后再进行下一步处理。这种模式使得代码更加清晰且易于维护。
在这个问题中,讨论的是 Nodeclub 源码中的 EJS 模板引擎以及 EventProxy
的使用。为了更好地理解这个问题,我们需要先了解 EventProxy
的功能。EventProxy
是一个帮助管理异步操作的模块,可以简化多步骤异步操作的逻辑。
代码解析
在 getTopicById
函数中,我们看到以下几个关键点:
-
创建
EventProxy
实例:var proxy = new EventProxy();
-
定义需要触发的事件:
var events = ['topic', 'tags', 'author', 'last_reply'];
-
分配事件处理程序:
proxy.assign(events, function (topic, tags, author, last_reply) { return callback(null, topic, tags, author, last_reply); }).fail(callback);
-
查询主题:
Topic.findOne({_id: id}, proxy.done(function (topic) { if (!topic) { proxy.emit('topic', null); proxy.emit('tags', []); proxy.emit('author', null); proxy.emit('last_reply', null); return; } proxy.emit('topic', topic); }));
-
查询标签:
TopicTag.find({topic_id: topic._id}, proxy.done(function (topic_tags) { var tags_id = []; for (var i = 0; i < topic_tags.length; i++) { tags_id.push(topic_tags[i].tag_id); } Tag.getTagsByIds(tags_id, proxy.done('tags')); }));
-
查询作者:
User.getUserById(topic.author_id, proxy.done('author'));
-
查询最后回复:
if (topic.last_reply) { Reply.getReplyById(topic.last_reply, proxy.done(function (last_reply) { proxy.emit('last_reply', last_reply || null); })); } else { proxy.emit('last_reply', null); }
重点理解
- EventProxy 的核心是管理多个异步操作,并在所有操作完成后触发一个最终的回调。
- 在上述代码中,
proxy.done
方法用于指定每个异步操作完成后的回调函数。 proxy.assign
方法用于将多个事件绑定到一个回调函数,并在所有事件触发后执行该回调函数。- 如果某个操作失败,
proxy.fail
会捕获并处理错误。
通过这种方式,EventProxy
可以有效地管理复杂的异步逻辑,确保所有数据准备好后再进行下一步操作。