本课我们来创建路由处理模块
上一课,我们已经学会了怎么样去创建路由模块, 那么要真正的实现路由,还必须要添加具体的处理逻辑。
那么在哪里添加呢?
在routes.js 里的 get函数里添加下面的代码来处理
if (pathname == '/home') {
//do something
} else if (pathname == '/about') {
// do something
}
这样子,功能上是没问题的。不过并不是一个好的方案。为什么呢?
因为,上一课我们实现的路由模块,虽然简单,但是很纯粹。 它只负责实现路由的过程。
路由结束之后,具体采取什么行动,它并不负责
如果把路由结束后的 具体行为 也写入到routes模块,那么, 当有成千上万个路由请求时, 将无法很好的扩展routes模块。
而且,如果routes里实现了具体的处理逻辑,那么这个模块也就只能成为一个具体的服务器的模块,而不再是一个可重用的,通用用的routes模块了。
(假如,我又要实现一个新的服务器server2.js, /home 的逻辑是完成不一样的,那么直接把routes.js拿来使用显示不能得到正确的结果)
因此,我们应该针对 路由结束后的具体行为编写一个单独的模块, 在此把它称为requestHandler模块,在模块中,为每一个请求处理 ,添加一个对应的函数,最后把这些函数作为模块的方法导出:
编写模块我们已经很熟悉了, 直接上代码
上一课,我们已经学会了怎么样去创建路由模块, 那么要真正的实现路由,还必须要添加具体的处理逻辑。
那么在哪里添加呢?
在routes.js 里的 get函数里添加下面的代码来处理
if (pathname == '/home') {
//do something
} else if (pathname == '/about') {
// do something
}
这样子,功能上是没问题的。不过并不是一个好的方案。为什么呢?
因为,上一课我们实现的路由模块,虽然简单,但是很纯粹。 它只负责实现路由的过程。
路由结束之后,具体采取什么行动,它并不负责
如果把路由结束后的 具体行为 也写入到routes模块,那么, 当有成千上万个路由请求时, 将无法很好的扩展routes模块。
而且,如果routes里实现了具体的处理逻辑,那么这个模块也就只能成为一个具体的服务器的模块,而不再是一个可重用的,通用用的routes模块了。
(假如,我又要实现一个新的服务器server2.js, /home 的逻辑是完成不一样的,那么直接把routes.js拿来使用显示不能得到正确的结果)
因此,我们应该针对 路由结束后的具体行为编写一个单独的模块, 在此把它称为requestHandler模块,在模块中,为每一个请求处理 ,添加一个对应的函数,最后把这些函数作为模块的方法导出:
编写模块我们已经很熟悉了, 直接上代码
//@name requestHandler.js
//@author Bob
function a(){
console.log("welcome to visit a ^_^ ");
}
function b(){
console.log("welcome to visit b @_@ ");
}
exports.a = a;
exports.b = b;
就是这么简单,对不对。
下面说点不简单的。怎么使用?
我们之前已经学过 什么是注入依赖 以及它的好处了,所以这一次仍然采用注入依赖来 在routes模块中使用requestHandler模块。
直观的想法是在 routes.get(pathname)中 再注入对应的处理函数 如: routes.get(pathname, requestHandler.a);
但是有一个问题,目前我们一共创建了 index.js, server.js ,routes.js, requestHandler.js,它们间的依赖关系是
index->server->routes->requestHandler
想把requestHandler.a 从index一层层注入进来是不现实的,因为routes模块君,你从server那里拿到了路径名,你才应该知道是调用a ,还是调用b啊, 但是如果硬编码成 if (pathname=='/a') { requestHandler.a(); }又会造成routes模块不通用,以及维护验证的问题。这可如何是好?
是得好好考虑一下,现在的问题是,routes拿到了pathname,又不能硬编码出具体的函数名。 一面是具体的pathname,一面是不具体的函数,怎么才能建立起联系呢?
答案是 “关联数组” ! (这里其实是一个对象config,对象的 每一个pathname映射到一个对应的函数)
我们只要编写好一个关联对象,然后把它从index 逐层的注入到routes模块。这样routes模块就可以根据注入的这个对象config,以及具体的pathname 来执行一个固定的语句了 config[pathname]();
这样以来routes模块就是固定不变的,可以被不同的服务器原装引用, 且依赖注入了config对象,实现了routes与requestHandler模块的解耦合
下面我们回到index.js里来具体编写这个config对象, 并把它注入到server里
下面说点不简单的。怎么使用?
我们之前已经学过 什么是注入依赖 以及它的好处了,所以这一次仍然采用注入依赖来 在routes模块中使用requestHandler模块。
直观的想法是在 routes.get(pathname)中 再注入对应的处理函数 如: routes.get(pathname, requestHandler.a);
但是有一个问题,目前我们一共创建了 index.js, server.js ,routes.js, requestHandler.js,它们间的依赖关系是
index->server->routes->requestHandler
想把requestHandler.a 从index一层层注入进来是不现实的,因为routes模块君,你从server那里拿到了路径名,你才应该知道是调用a ,还是调用b啊, 但是如果硬编码成 if (pathname=='/a') { requestHandler.a(); }又会造成routes模块不通用,以及维护验证的问题。这可如何是好?
是得好好考虑一下,现在的问题是,routes拿到了pathname,又不能硬编码出具体的函数名。 一面是具体的pathname,一面是不具体的函数,怎么才能建立起联系呢?
答案是 “关联数组” ! (这里其实是一个对象config,对象的 每一个pathname映射到一个对应的函数)
我们只要编写好一个关联对象,然后把它从index 逐层的注入到routes模块。这样routes模块就可以根据注入的这个对象config,以及具体的pathname 来执行一个固定的语句了 config[pathname]();
这样以来routes模块就是固定不变的,可以被不同的服务器原装引用, 且依赖注入了config对象,实现了routes与requestHandler模块的解耦合
下面我们回到index.js里来具体编写这个config对象, 并把它注入到server里
var server = require("./server");
var routes = require("./routes");
var requestHandler = require("./requestHandler");
var config = {};
config['/a'] = requestHandler.a;
config['/a'] = requestHandler.a;
server.start(routes.get ,config);
Server.js再注入给routes.js
function start(get , config){
var http = require("http");
var url = require("url");
var querystring = require("querystring");
var server = http.createServer(function(request, response){
response.writeHead(200, {"Content-Type":"text/plain"});
var url_obj = url.parse(request.url);
response.write("\n pathname:"+url_obj.pathname);
response.write("\n query:"+url_obj.query);
get(url_obj.pathname , config);
var qs = querystring.parse(url_obj.query);
response.write("\n a:"+qs["a"]);
response.write("\n b:"+qs.b);
response.write("\n c:"+qs.c);
response.end();
});
server.listen(8888);
}
exports.start = start;
routes.js 收到的依赖对象config, 前根据 pathname, 来调用正确的requestHandler函数来处理
function get(pathname , config){
console.log("routes to :"+pathname);
if (typeof(config[pathname]) === 'function') {
config[pathname]();
} else{
console.log("routes to empty path: " + pathname);
}
};
exports.get = get;
大功造成。运行 node index
打开浏览器访问
http://localhost:8888/abcd?c=xx&b=joke&a=8
会在CLI里看到 routes to empty path: /abcd
打开浏览器访问
http://localhost:8888/a?c=xx&b=joke&a=8
会在CLI里看到 welcome to visit a ^_^
收工!