进阶之初探nodeJS


Posted in NodeJs onJanuary 24, 2017

一、前言

在"初探nodeJS"随笔中,我们对于node有了一个大致地了解,并在最后也通过一个示例,了解了如何快速地开启一个简单的服务器。

今儿,再次看了该篇随笔,发现该随笔理论知识稍多,适合初级入门node,固萌生一个想法--想在该篇随笔中,通过一步步编写一个稍大一点的node示例,让我们在整体上更加全面地了解node。

so,该篇随笔是建立在"初探nodeJS"之上的,固取名为"进阶之初探nodeJS"。

好了,侃了这多,那么我们即将实现一个什么样的示例呢?

示例说明,如下:

用户通过url之127.0.0.1/login进入登入页面,待用户输入账户名后(密码选项输不输都无所谓,只是为了页面合理),点击提交,进入home页面。

node服务端,怎么处理的呢?通过URL判断,当为/login时,服务端读取login.html的内容,并将其传递到前端显示;当为/home时,服务端读取home.html的内容,并将login.html中提交的账号名与home.html中的模板替换,最后将结果传递到前端显示。

大体流程,如下:

进阶之初探nodeJS

示例最终实现效果,如下:

进阶之初探nodeJS

好了,了解示例需求,下面我们就一起来一步一步实现上述Demo吧。

二、前端文件准备

要实现上述效果,我们首先简单地准备两个页面login.html、home.html以及一张贺岁图片,显而易见,供接下来node读取它们并将它们呈现到浏览器中,使用。

在上述说明中,已讲过node服务器是通过路由来判断,加载哪张页面,固我们将login.html中form的action写作'./home',以达到我们的目的,请求方式嘛,使用的当然是post咯。

且,因为我们要将在login.html中填写的账户名动态地与home.html结合,固home.html中的“称呼”位置,不能写死,因此我们利用{name}来占位,随后利用node动态替换。

好了,简易编写的login.html、home.html以及贺岁图,如下:

<!DOCTYPE html>
<head>
 <meta charset="utf-8">
 <style>
 form {
 text-align:center;
 }
 </style>
</head>
 <body>
 <form action="./home" method="post">
 账户:<input type="text" name="name"/><br/>
 密码:<input type="password" name="password"/><br/>
 <input type="submit" value="提交"/>
 </form> 
 </body>
</html>

login.html
<!DOCTYPE html>
<head>
 <meta charset="utf-8">
 <style>
 body {
 text-align:center;
 }
 span {
 color: blue;
 }
 </style>
</head>
 <body>
 <div>
 <span>{name}</span>,新de一年,一定要开心哦~
 </div>
 <img src="./getPic"/> 
 </body>
</html>

home.html

进阶之初探nodeJS

三、编写node服务

上述中,我们所需要的前端文件已经准备完毕,接下来就是通过node来编写服务,将它们串联起来咯。

首先,我们搭建一个主文件,取名为main.js吧,作用不言而喻,主入口嘛,如果我们在代码编写完毕后,想要启动服务,就node main.js就OK咯。

如下:

'use strict';
var http = require('http');
var server = http.createServer();
server.on('request',function(req, res){
 //排除favicon.ico请求
 if(req.url != '/favicon.ico'){
 //TODO
 }else{
 res.end();
 }; 
}).listen('80');
console.log('Server running!');

接着,我们就一起来逐步完善这个主文件。

在“前言”中我们提过,当一个请求来到服务中,我们采取获取URL的路径,来判断接下来的操作,已到达降低耦合性的目的。

所以,在主程序中,我们得利用url这个模块,来获得url中的相关路径,并通过正则来得到第一个路径名,通过接下来的路由模块,处理。

如下:

'use strict';
var http = require('http');
var url = require('url');
var server = http.createServer();
server.on('request',function(req, res){
 if(req.url != '/favicon.ico'){
 //获取路径
 let pathname = url.parse(req.url).pathname;
 pathname = pathname.match(/\w+/)[0];
 //router具体,待写...
 router[pathname](req, res);
 }else{
 res.end();
 }; 
}).listen('80');
console.log('Server running!');

好了,接下来,我们就一起来编写router这个模块吧。

在我们示例中,router无外乎就是处理login、home以及图片请求getPic,所以,我们将router模块基本骨架,暂定如下:

'use strict';
var router = {
 login: function(req, res){
 //TODO 
 },
 home: function(req, res){
 //TODO
 },
 getPic: function(req, res){
 //TODO
 }
};
module.exports = router;

且,我们发现login、home以及getPic这三个操作,有很多共通之处,如都会读取服务端本地文件,以及将读取的文件,写入响应体中,固我们将这些操作提取出来,作为operation模块。

在operation模块中,我们需要使用到node内置'fs'这个模块来读取文件,'fs'模块我们将会用到如下方法:

1、fs.readFileSync--同步读取文件

2、fs.readFile--异步读取文件

3、fs.writeFileSync--同步写入文件

4、fs.writeFile--异步写入文件

需要注意的是,读取图片也就使用的fs.readFileSync/fs.readFile,不过就是第二个参数还需加上'binary',二进制嘛。

'use strict';
var fs = require('fs');
var operationFile = {
 readFileSync: function(path, callback){//同步读取文件
 let data = fs.readFileSync(path, 'utf-8');
 syncOperation(callback, data, '同步读取文件完毕');
 },
 readFileAsync: function(path, callback){//异步读取文件
 fs.readFile(path, function(err, data){
 asyncOperation(err, callback, data, '异步读取文件成功');
 }); 
 },
 writeFileSync: function(path, data, callback){//同步写入文件
 fs.writeFileSync(path, data);
 syncOperation(callback, null, '同步写入文件完毕'); 
 },
 writeFile: function(path, data, callback){//异步写入文件
 fs.writeFile(path, data, function(err){
 asyncOperation(err, callback, null, '异步写入文件完毕');
 });
 },
 readImg: function(path, callback){//异步读取图片
 fs.readFile(path, 'binary', function(err, file){
 asyncOperation(err, callback, file, '异步读取图片完毕');
 });
 } 
};
function syncOperation(callback, data, msg='操作成功'){
 if(typeof callback === 'function'){
 callback(data);
 }else{
 console.log(msg);
 } 
}
function asyncOperation(err, callback, data, msg='操作成功'){
 if(err){
 console.log(err);
 }else if(typeof callback === 'function'){
 callback(data);
 }else{
 console.log(msg);
 } 
}
module.exports = operationFile;

operation模块

另外,我们在login.html中提交表单时,使用到了post请求,那么在node服务中应该怎么接收传来的实体呢?

node是采用的监听'data'来接收post方法实体信息,通过'end'来监听接收信息完毕事件。

而,node接收get请求参数就没这么复杂,直接获取url后的查询字符串即可。

好了,我们将获取post、get请求参数,也写为一个模块,取名为getQuery,如下:

'use strict';
var url = require('url');
var querystring = require('querystring');
module.exports = {
 fromGet: function(req, res, callback){
 var data = url.parse(req.url, true).query;
 callback(data); 
 },
 fromPost: function(req, res, callback){
 var data = '';
 req.on('data', function(chunk){
 data += chunk;
 });
 req.on('end', function(){
 data = querystring.parse(data);
 callback(data);
 });
 }
};

getQuery模块

最后,就是在router模块中,引入operation、getQuery模块,完善login、home以及getPic方法咯。

在这里需要注意的是getPic方法,因为是处理的图片,所以响应头得写成'image/jpeg',如下:

res.writeHead(200, {'Content-Type':'image/jpeg'});

好了,大致思路已理清,详细代码请见github.

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

NodeJs 相关文章推荐
ubuntu下安装nodejs以及升级的办法
May 08 NodeJs
Nodejs获取网络数据并生成Excel表格
Mar 31 NodeJs
nodejs基础应用
Feb 03 NodeJs
基于Nodejs利用socket.io实现多人聊天室
Feb 22 NodeJs
nodejs实现邮件发送服务实例分享
Mar 29 NodeJs
nodejs爬虫遇到的乱码问题汇总
Apr 07 NodeJs
使用nodeJs来安装less及编译less文件为css文件的方法
Nov 20 NodeJs
nodejs 生成和导出 word的实例代码
Jul 31 NodeJs
Nodejs使用Mongodb存储与提供后端CRD服务详解
Sep 04 NodeJs
nodejs log4js 使用详解
May 31 NodeJs
nodejs实现百度舆情接口应用示例
Feb 07 NodeJs
分享node.js实现简单登录注册的具体代码
Apr 26 NodeJs
用nodejs搭建websocket服务器
Jan 23 #NodeJs
NodeJS遍历文件生产文件列表功能示例
Jan 22 #NodeJs
nodejs实现发出蜂鸣声音(系统报警声)的方法
Jan 18 #NodeJs
nodejs的压缩文件模块archiver用法示例
Jan 18 #NodeJs
nodejs 实现钉钉ISV接入的加密解密方法
Jan 16 #NodeJs
简单实现nodejs上传功能
Jan 14 #NodeJs
基于NodeJS+MongoDB+AngularJS+Bootstrap开发书店案例分析
Jan 12 #NodeJs
You might like
一些操作和快捷键的理解和讨论
2020/03/04 星际争霸
用PHP和MySQL保存和输出图片
2006/10/09 PHP
PHP中遇到BOM、编码导致json_decode函数无法解析问题
2014/07/02 PHP
浅谈php安全性需要注意的几点事项
2014/07/17 PHP
CodeIgniter使用smtp服务发送html邮件的方法
2015/06/10 PHP
thinkPHP实现多字段模糊匹配查询的方法
2016/12/01 PHP
原生js实现半透明遮罩层效果具体代码
2013/06/06 Javascript
关于javascript event flow 的一个bug详解
2013/09/17 Javascript
javascript使用定时函数实现跳转到某个页面
2013/12/25 Javascript
firefox下jquery ajax返回object XMLDocument处理方法
2014/01/26 Javascript
jquery实现人性化的有选择性禁用鼠标右键
2014/06/30 Javascript
js实现图片和链接文字同步切换特效的方法
2015/02/20 Javascript
JavaScript添加随滚动条滚动窗体的方法
2016/02/23 Javascript
详解Angular CLI + Electron 开发环境搭建
2017/07/20 Javascript
在Vue中获取组件声明时的name属性方法
2018/09/12 Javascript
解决layui 表单元素radio不显示渲染的问题
2019/09/04 Javascript
浅谈VUE中演示v-for为什么要加key
2020/01/16 Javascript
[00:32]2018DOTA2亚洲邀请赛VGJ.T出场
2018/04/03 DOTA
python中getattr函数使用方法 getattr实现工厂模式
2014/01/20 Python
跟老齐学Python之从if开始语句的征程
2014/09/14 Python
python爬取足球直播吧五大联赛积分榜
2018/06/13 Python
python argparser的具体使用
2019/11/10 Python
django实现类似触发器的功能
2019/11/15 Python
利用PyCharm操作Github(仓库新建、更新,代码回滚)
2019/12/18 Python
基于python纯函数实现井字棋游戏
2020/05/27 Python
FOREO斐珞尔官方旗舰店:LUNA露娜洁面仪
2018/03/11 全球购物
巴西服装和鞋子购物网站:Marisa
2018/10/25 全球购物
精致的手工皮鞋:Shoe Embassy
2019/11/08 全球购物
线程的基本概念、线程的基本状态以及状态之间的关系
2012/10/26 面试题
软件测试有哪些?什么是配置项?
2012/02/12 面试题
公关关系专员的自我评价分享
2013/11/20 职场文书
投资意向协议书
2015/01/29 职场文书
高中班主任心得体会
2016/01/07 职场文书
课改心得体会范文
2016/01/25 职场文书
详细了解java监听器和过滤器
2021/07/09 Java/Android
Anaconda配置各版本Pytorch的实现
2021/08/07 Python