You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionnext(err){
....//省略了一些代码// find next matching layervarlayer;varmatch;varroute;while(match!==true&&idx<stack.length){layer=stack[idx++];match=matchLayer(layer,path);route=layer.route;if(typeofmatch!=='boolean'){// hold on to layerErrorlayerError=layerError||match;}if(match!==true){continue;}if(!route){// process non-route handlers normallycontinue;}
....//省略一些源码}// no matchif(match!==true){returndone(layerError);}// store route for dispatch on changeif(route){req.route=route;}
.....// this should be done for the layerself.process_params(layer,paramcalled,req,res,function(err){if(err){returnnext(layerError||err);}if(route){returnlayer.handle_request(req,res,next);}trim_prefix(layer,layerError,layerPath,path);});}
methods.forEach(function(method){Route.prototype[method]=function(){varhandles=flatten(slice.call(arguments));for(vari=0;i<handles.length;i++){varhandle=handles[i];if(typeofhandle!=='function'){vartype=toString.call(handle);varmsg='Route.'+method+'() requires callback functions but got a '+type;thrownewError(msg);}
....varlayer=Layer('/',{},handle);layer.method=method;this.methods[method]=true;this.stack.push(layer);}returnthis;};});
这种方法比较灵活,不需要将所有的method遍历一遍。
总结
express的源码还是有点复杂的,新手初涉,可能有一些地方理解得不是很到位的,欢迎一起交流
The text was updated successfully, but these errors were encountered:
最近在研究
experss
,在造过一个简单的轮子之后,想通过研究一下它的源码来了解一下内部的实现原理,如有不对的地方希望得到大家的指正。研究的
express
版本为4.15.0
,应该算是比较新的版本了。文件结构及内容
上图中的目录结构比较清晰,
router
目录中主要是router
路由的功能,middleware
目录是中间件的一些功能。比较重要的是express.js
和application.js
还有router
文件夹中的文件。express.js
中很简单,只是暴露了一个工厂函数createApplication
,这个函数虽然简洁,但是却完成了生成一个完成app
的整个过程,具体代码如下:在
application.js
中,可以看到app.listen
的实现:由此就可以知道使用
express
实例化一个项目,其实和使用原生node
创建一个应用的步骤差不多,只是express
进行了一层封装而已。application.js
这个文件主要是暴露了express
内部的一些api
,比如app.render(),app.param(),app.set()
等。路由
express
的router
中总共包含了三个文件,index.js
,route.js
和layer.js
,并且分别定义了router,route,layer
三个构造函数,其中router
和route
这两个对象都包含stack
这个成员属性,也就是中间件数组。并且router
和route
里面的stack
也不一样,如下图:如上图可见,
router
中的stack
数组是由route
对象组成的,而route
中的stack
则是由layer
数组组成的。三者关系可以描述成下图:route
对象代表的是路由对象,每一条路由都会实例化一个route
对象,而router
则是一个路由集合,在上一篇中曾提到router
是一个“微型应用程序”,这说明router
和route
之间的关系是一个包含与被包含的关系,前者的功能更强大,后者只是处理单条路由的一些功能。路由的整个功能和逻辑顺序大概如下:
在触发一个路由的时候,比如访问
/login
时,会执行router
的成员函数handle()
,在这个函数中会将传进来的req
的url
做一些处理,比如获取url
里面的参数,并会遍历stack
数组中的每一个layer
,遍历主要是通过next()
实现的,这个next()
主要是非路由中间件的next()
函数,具体代码如下:遍历过程中会执行一个
match()
,如果匹配成功(断点发现当stack.name=router
的时候会匹配成功),则会去执行route
中的dispatch
方法,则获取当前route
的stack
数组并通过next()
再进行遍历一次。当再次匹配成功之后,就会去调用layer
对象的handle_request()
方法。也就是调用中间件函数,这个函数的代码如下:上面也是执行中间件的主要部分,首先是判断路由函数中传进来的回调函数的参数个数,若大于3,则属于路由中间件,则首先处理
next()
,这里的next()
函数代码如下(定义在route.js
文件中:这个
next()
主要是处理路由中间件的,不断遍历,使得中间件一个个执行。对于路由中间件和非路由中间件,两者也是有区别的,路由中间件的定义是在router/index.js
中的route
原型方法中,具体代码如下:从上面代码可以看出,路由中间件中的
route
不为空值,且为一个route
对象,并且该对象中有methods
的一个成员属性,用来定义一些路由方法。再来看看非路由中间件的定义方法,放在了router/index.js
中的use
原型方法中,具体代码如下:从上面源码可以看出,非路由中间件中的
route
属性值为undefined
,当使用app.use()
时其实也就是触发了router.use()
方法。动态添加
method
源码中并没有直接遍历路由中的每一种方法,比如
get,post,put
,而是动态添加,不论是最后导出的app
示例,还是route
中对方法的处理,都是使用的这种方式,具体代码如下:在
route
对象中,同样定义了这样一个处理method
的操作:这种方法比较灵活,不需要将所有的
method
遍历一遍。总结
express
的源码还是有点复杂的,新手初涉,可能有一些地方理解得不是很到位的,欢迎一起交流The text was updated successfully, but these errors were encountered: