how2j.cn

下载区
文件名 文件大小
nodejs.rar 1k
使用站长秘制下载工具
步骤 1 : server.js 的问题   
步骤 2 : 路由概念   
步骤 3 : 先运行,看到效果,再学习   
步骤 4 : 模仿和排错   
步骤 5 : 路由代码实现   
步骤 6 : 业务处理模块 requestHandlers.js   
步骤 7 : 路由模块 router.js   
步骤 8 : 服务器模块 server.js   
步骤 9 : 入口主模块 index.js   
步骤 10 : 思路整理   

步骤 1 :

server.js 的问题

edit
首先回顾一下前面 server.js 的代码, 这个代码很清爽,也很容易维护。 但是当业务开始略微复杂的时候,怎么办呢?
比如业务上需要通过访问 /listCategory 显示所有的分类,又需要通过访问 /listProduct 显示所有的产品,那么仅仅通过一个 service(request, response) 方法来进行维护不是很麻烦吗
所以在这个时候,就会引入路由的概念了。
var http = require('http'); function service(request, response) { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello Node.js'); } var server = http.createServer(service); server.listen(8088);
var http = require('http');
function service(request, response) {
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.end('Hello Node.js');
}
var server = http.createServer(service);
server.listen(8088);
如果没有路由的概念,那么无论是访问/listCategory路径 还是访问 /listProduct 路径,都是在service(request,response) 函数里做的。

那么引入路由的概念的话,就是指访问 /listCategory 路径,会访问 listCategory函数。 而访问 /listProduct 路径,就会访问 listProduct 函数,这样子维护起来就容易多了。

如代码所示,会提供 listCategory() 函数。
再如图所示,访问地址 /listCategory 就会显示 listCategory() 函数的返回值。
注: 这里的代码仅仅是片段,接下来才会给出完整的代码
路由概念
function listCategory() { return "a lot of categorys"; } function listProduct() { return "a lot of products"; }
function listCategory() {  
	return "a lot of categorys";
}  
  
function listProduct() {  
	return "a lot of products";
}  
步骤 3 :

先运行,看到效果,再学习

edit
老规矩,先下载右上角的可运行项目,配置运行起来,确认可用之后,再学习做了哪些步骤以达到这样的效果。
运行方式 : (并不是 node server.js)

node index.js

然后访问测试地址:
http://127.0.0.1:8088/listCategory
就可以看到如图所示的效果了
先运行,看到效果,再学习
在确保可运行项目能够正确无误地运行之后,再严格照着教程的步骤,对代码模仿一遍。
模仿过程难免代码有出入,导致无法得到期望的运行结果,此时此刻通过比较正确答案 ( 可运行项目 ) 和自己的代码,来定位问题所在。
采用这种方式,学习有效果,排错有效率,可以较为明显地提升学习速度,跨过学习路上的各个槛。

推荐使用diffmerge软件,进行文件夹比较。把你自己做的项目文件夹,和我的可运行项目文件夹进行比较。
这个软件很牛逼的,可以知道文件夹里哪两个文件不对,并且很明显地标记出来
这里提供了绿色安装和使用教程:diffmerge 下载和使用教程
步骤 5 :

路由代码实现

edit
为了达到前面的路由效果,需要多个模块协同配合达到这个效果。 所谓的多个模块,其实就是多个.js文件里的多个函数互相配合。
步骤 6 :

业务处理模块 requestHandlers.js

edit
首先是业务处理模块 ,即提供 listCategory函数和listProduct()函数
function listCategory() { return "a lot of categorys"; } function listProduct() { return "a lot of products"; } exports.listCategory = listCategory; exports.listProduct = listProduct;
function listCategory() {  
	return "a lot of categorys";
}  
  
function listProduct() {  
	return "a lot of products";
}  

exports.listCategory = listCategory;  
exports.listProduct = listProduct;  
步骤 7 :

路由模块 router.js

edit
router函数第一个参数 handle 是一个数组,第二个参数是 路径。
这个模块,乍一看会有点晕,要结合后面的模块来看
function route(handle, pathname) { if (typeof handle[pathname] === 'function') { return handle[pathname](); } else { return pathname + ' is not defined'; } } exports.route = route;
function route(handle, pathname) {  
  if (typeof handle[pathname] === 'function') {  
    return handle[pathname]();  
  } else { 
	return pathname + ' is not defined';
  }  
}  
exports.route = route;  
步骤 8 :

服务器模块 server.js

edit
这个就是启动服务器的模块,同样的。。。还是要结合后面的代码来看
var http = require("http"); var url = require("url"); function start(route, handle) { function onRequest(request, response) { var pathname = url.parse(request.url).pathname; var html = route(handle, pathname); response.writeHead(200, {"Content-Type": "text/plain"}); response.write(html); response.end(); } http.createServer(onRequest).listen(8088); } exports.start = start;
var http = require("http");  
var url = require("url");  
  
function start(route, handle) {  
  function onRequest(request, response) {  
    var pathname = url.parse(request.url).pathname;  
    var html = route(handle, pathname);  
    response.writeHead(200, {"Content-Type": "text/plain"});  
    response.write(html);  
    response.end();  
  }  
  
  http.createServer(onRequest).listen(8088);  
}  
  
exports.start = start;  
步骤 9 :

入口主模块 index.js

edit
与以往启动使用 server.js不同,带路由功能,一般都会通过 index.js 启动,所以index.js 就是入口模块。
handle 是一个数组,映射了不同的访问路径与 业务处理模块对应函数的一一对应关系。

handle["/listCategory"] = requestHandlers.listCategory;

这就表示访问路径 /listCategory的话,就会交给函数 requestHandlers.listCategory 来处理。
var server = require("./server"); var router = require("./router"); var requestHandlers = require("./requestHandlers"); var handle = {} handle["/listCategory"] = requestHandlers.listCategory; handle["/listProduct"] = requestHandlers.listProduct; server.start(router.route, handle);
var server = require("./server");  
var router = require("./router");  
var requestHandlers = require("./requestHandlers");  

var handle = {}  
handle["/listCategory"] = requestHandlers.listCategory;  
handle["/listProduct"] = requestHandlers.listProduct;  
  
server.start(router.route, handle);  
1. 通过如下方式启动服务器

node index.js

2. index.js 调用了 server.start 函数,并且传递了 router.js 里route 函数和handle数组作为参数
3. serverl.js 通过了8088端口启动了服务。 然后用 onRequest 函数来处理业务
3.1 在 onRequest 中,首先获取 访问路径 pathname
3.2 然后调用 router.js 的route 函数,并把pathname 和 handle数组传递进去
4. 在router.js 中,通过pathname为下标获调用真正的业务函数,并把业务函数的返回值返回出去。
4.1 如果找不到,比如访问 /listUser 这个路径就没有在 handle 数组中找到对应,那么就会返回 listUser is not defined.
5. 当访问地址是 /listCategory的时候, 真正的业务函数 requestHandlers.js 中的 listCategory() 就会被调用,并返回业务 Html 代码 : "a lots of categorys".

通过以上的方式,最后就落实在了 requestHandlers.js 的业务代码上面了。
虽然看上去略复杂,但是以后如果要开发新的功能,比如 /listUser, 那么就只需要新增加 listUser 函数,并在 index.js 中对他进行映射即可了。


HOW2J公众号,关注后实时获知布最新的教程和优惠活动,谢谢。


问答区域    
2019-07-09 为什么 handle[pathname](); 这个后面要加上括号啊?
louisCao
为什么 handle[pathname](); 这个后面要加上括号啊?







回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到




2019-06-10 handle是字典,是JSON对象啊老铁们
rockmanzzx







回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到




2019-03-27 被楼下两位误导了,花了点时间理解。2位也都是错的。这里说下我的理解和流程分析
2018-11-04 handle应该是一个对象
2018-08-20 流程分析




提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 前端部分-node.js-路由 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 1001964108
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: http://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图