高级节点的初步研究
一、前言
在《探索节点》一文中,我们对节点有了一个大概的了解,最后通过一个例子,我们知道了如何快速启动一个简单的服务器。
今天再看一遍这篇短文,发现这篇短文理论知识多了一点,适合初学者去节点,我有一个想法——我想在这篇短文中一步一步写一个稍微大一点的节点例题,这样我们从整体上更全面地理解节点。
因此,本文以“初步探索节点”为基础,命名为“高级初步探索节点”。
好了,说了这么多,我们要实施什么样的榜样?
例子如下:
用户通过127.0.0.1/login的url进入登录页面。用户输入帐户名后(密码选项输入与否无关紧要,只是为了页面合理),点击提交进入首页。
节点服务器,如何处理?通过网址判断,当它是/登录时,服务器读取login.html的内容并传输到前端显示;当它是/home时,服务器读取home.html的内容,用home.html的模板替换在login.html提交的帐户名,最后将结果传输到前端进行显示。
一般流程如下:
该实例最终达到如下效果:
好了,在了解了示例需求之后,让我们一步一步地实现上面的演示。
二、前端文件准备
为了达到上述效果,我们首先简单准备了两个页面,即login.html和home.html,以及一张新年图片,显然可供node阅读并呈现给浏览器使用。
在上面的描述中,已经说过节点服务器通过路由来判断加载哪个页面,所以我们将login.html表单的动作写成。/家’,以达到我们的目的。请求方法当然是post。
另外,因为我们要动态组合login.html填写的帐户名和home.html,并固定home.html的地址位置,所以不能写死,所以我们用{name}来占据这个地方,然后用node来动态替换。
好了,login.html、home.html和年画的简单汇编如下:
!DOCTYPE html head meta charset=' utf-8 '样式表单{ text-align : center;}/style/head body form action='。/home '方法=' post '帐户:input type=' text ' name=' name '/br/password:input type=' password ' name=' password '/br/input type=' submit ' value=' submit '/form/。DOCTYPE html head meta charset=' utf-8 '样式正文{ text-align : center;} span { color: blue}/style/head body div span { name }/span,新的一年你一定要开心~/div img src=' http:/getpic '/body/html home . html
第三,编写节点服务
在上面,我们需要的前端文件已经准备好了,下一步就是通过node编写服务,并将其串联起来。
首先,我们构建一个主文件,命名为main.js,它的作用不言而喻。如果我们想在编写完代码后启动服务,那么node main.js就可以了。
如下所示:
使用“严格”;var http=require(' http ');var server=http . CreateServer();Server.on ('request ',function (req,RES){//从if(req.url!='/fav icon . ico '){//TODO } else { RES . end();};}).倾听(' 80 ');控制台.日志('服务器正在运行!');然后,我们将逐步完善这个主文档。
前言中提到,当一个请求来到服务时,我们采取获取URL的路径来判断下一个操作是否达到了减少耦合的目的。
因此,在主程序中,我们必须使用url模块来获取url中的相关路径,并通过正则化获得第一个路径名,然后通过下一个路由模块进行处理。
如下所示:
使用"严格";var http=require(' http ');var URL=必选(' URL ');var服务器=http。CreateServer();server.on('request ',function(req,res){ if(req.url!='/favicon.ico'){ //获取路径让pathname=url.parse(req.url).路径名;路径名=路径名。匹配(/\ w/)[0];//路由器具体,待写.路由器[路径名](请求,资源);} else { RES . end();};}).倾听(' 80 ');控制台。日志('服务器正在运行!');好了,接下来,我们就一起来编写路由器这个模块吧。
在我们示例中路由器无外乎就是处理登录、主页以及图片请求getPic,所以,我们将路由器模块基本骨架,暂定如下:
使用"严格";var路由器={ login:函数(请求,资源){//待办事项}、主页:函数(请求,资源){//待办事项}、getPic:函数(req,RES){//TODO } };module.exports=路由器;且,我们发现登录、主页以及getPic这三个操作,有很多共通之处,如都会读取服务端本地文件,以及将读取的文件,写入响应体中,固我们将这些操作提取出来,作为操作模块。
在操作模块中,我们需要使用到结节内置fs '这个模块来读取文件,' fs '模块我们将会用到如下方法:
1、fs.readFileSync -同步读取文件
2、fs.readFile -异步读取文件
3、fs.writeFileSync -同步写入文件
4、fs.writeFile -异步写入文件
需要注意的是,读取图片也就使用的fs.readFileSync/fs.readFile,不过就是第二个参数还需加上二进制,二进制嘛。
使用"严格";var fs=require(' fs ');var操作文件={ readfilesync :函数(路径,回调){//同步读取文件让数据=fs.readFileSync(路径,' utf-8 ');同步操作(回调,数据,)同步读取文件完毕');},readFileAsync:函数(路径,回调){//异步读取文件fs.readFile(路径,函数(呃,数据){ asyncOperation(错误,回调,数据)'异步读取文件成功');});},writeFileSync:函数(路径、数据、回调){//同步写入文件fs.writeFileSync(路径,数据);同步操作(回调,null,)同步写入文件完毕');},writeFile:函数(路径、数据、回调){//异步写入文件fs.writeFile(路径,数据,函数(错误){ asyncOperation(错误,回调,null,'异步写入文件完毕');});},readImg:函数(路径,回调){//异步读取图片fs.readFile(路径,"二进制",函数(错误,文件){异步操作(错误,回调,文件)'异步读取图片完毕');});} };函数同步操作(回调,数据,msg='操作成功){ if(回调类型==' function '){ callback(数据);} else { console。日志(msg);} }函数异步操作(错误,回调,数据,msg='操作成功){ if(err){ console。日志(err);} else if(callback==' function '){ callback(data);} else { console。日志(msg);} }模块。导出=操作文件;操作模块
另外,我们在login.html中提交表单时,使用到了邮政请求,那么在结节服务中应该怎么接收传来的实体呢?
结节是采用的监听数据来接收邮政方法实体信息,通过结束来监听接收信息完毕事件。
而,节点接收得到请求参数就没这么复杂,直接获取全球资源定位器(统一资源定位符)后的查询字符串即可。
好了,我们将获取张贴、获取请求参数,也写为一个模块,取名为getQuery,如下:
使用"严格";var URL=必选(' URL ');var查询字符串=require('查询字符串');module.exports={ fromGet:函数(请求、res、回调){ var data=URL。解析(请求。网址,真的).查询;回调(数据);},来自Post:函数(req,res,callback){ var data=' ';req.on('data ',function(chunk){ data=chunk;});req.on('end ',function(){ data=查询字符串。解析(数据);回调(数据);});}};getQuery模块
最后,就是在路由器模块中,引入操作、获取查询模块,完善登录、主页以及getPic方法咯。
在这里需要注意的是getPic方法,因为是处理的图片,所以响应头得写成图像/jpeg ',如下:
res.writeHead(200,{ ' Content-Type ' : ' image/JPEG ' });
好了,大致思路已理清,详细代码请见github .
以上就是本文的全部内容。希望本文的内容能给大家的学习或工作带来一些帮助,也希望多多支持我们!