进阶之初探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 相关文章推荐
使用Nodejs开发微信公众号后台服务实例
Sep 03 NodeJs
nodejs URL模块操作URL相关方法介绍
Mar 03 NodeJs
Nodejs Stream 数据流使用手册
Apr 17 NodeJs
用nodejs的实现原理和搭建服务器(动态)
Aug 10 NodeJs
学习 NodeJS 第八天:Socket 通讯实例
Dec 21 NodeJs
初探nodeJS
Jan 24 NodeJs
Nodejs实现短信验证码功能
Feb 09 NodeJs
详解nodeJS之二进制buffer对象
Jun 03 NodeJs
nodejs acl的用户权限管理详解
Mar 14 NodeJs
nodejs简单读写excel内容的方法示例
Mar 16 NodeJs
解决nodejs的npm命令无反应的问题
May 17 NodeJs
详解NodeJS Https HSM双向认证实现
Mar 12 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
用PHP伪造referer突破网盘禁止外连的代码
2008/06/15 PHP
探讨如何把session存入数据库
2013/06/07 PHP
解析ajax事件的调用顺序
2013/06/17 PHP
php中并发读写文件冲突的解决方案
2013/10/25 PHP
Thinkphp模板标签if和eq的区别和比较实例分析
2015/07/01 PHP
phpMyAdmin无法登陆的解决方法
2017/04/27 PHP
PHP+Redis开发的书签案例实战详解
2019/07/09 PHP
Javascript 获取LI里的内容
2008/12/17 Javascript
js 覆盖和重载 函数
2009/09/25 Javascript
使用jQuery的将桌面应用程序引入浏览器
2010/11/19 Javascript
Extjs TimeField 显示正常时间格式的代码
2011/06/28 Javascript
修复ie8&amp;chrome下window的resize事件多次执行
2011/10/20 Javascript
Javascript数组的排序 sort()方法和reverse()方法
2012/06/04 Javascript
jQuery+CSS3折叠卡片式下拉列表框实现效果
2015/11/02 Javascript
详解nodejs中的process进程
2017/03/19 NodeJs
原生js封装自定义滚动条
2017/03/24 Javascript
详解Vue中状态管理Vuex
2017/05/11 Javascript
解决layer.open后laydate失效的问题
2019/09/06 Javascript
Vue实现多标签选择器
2019/11/28 Javascript
javascript设计模式之迭代器模式
2020/01/30 Javascript
[40:10]2015国际邀请赛全明星表演赛
2015/08/07 DOTA
Python中的__SLOTS__属性使用示例
2015/02/18 Python
Python实现确认字符串是否包含指定字符串的实例
2018/05/02 Python
python 提取key 为中文的json 串方法
2018/12/31 Python
tensorflow实现对张量数据的切片操作方式
2020/01/19 Python
Python 字符串处理特殊空格\xc2\xa0\t\n Non-breaking space
2020/02/23 Python
在django admin中配置搜索域是一个外键时的处理方法
2020/05/20 Python
Clearly澳大利亚:购买眼镜、太阳镜和隐形眼镜
2018/04/26 全球购物
医药营销专业个人自荐信
2013/09/29 职场文书
应届毕业生应聘自荐信
2013/12/07 职场文书
2014年煤矿工作总结
2014/11/24 职场文书
技术负责人岗位职责
2015/02/10 职场文书
《狼牙山五壮士》教学反思
2016/02/17 职场文书
导游词之天下银坑景区
2019/11/21 职场文书
Vue的列表之渲染,排序,过滤详解
2022/02/24 Vue.js
Win11更新失败并提示0xc1900101
2022/04/19 数码科技