61阅读

node.js开发实战详解-Node.js操作redis实现添加查询功能

发布时间:2017-11-29 所属栏目:node.js开发实战详解

一 : Node.js操作redis实现添加查询功能

在实际开发中,免不了要操作mysql,mongodb,redis等数据存储服务器。这里先简单介绍如何操作redis。

一个例子

关于redis服务端的安装这里不再介绍,重点不在这里。感兴趣的可以自行安装。

对于一个新的模块,我们需要在我们的项目中先安装redis模块才能用。

命令

 cnpm install redis 

新建一个redis.js的文件,代码如下:

 //引入redis var redis = require("redis"); //创建redis客户端 var client = redis.createClient("6379", "127.0.0.1"); //连接错误处理 client.on("error", function (error) {  console.log(error); }); //redis验证 (如果redis没有开启验证,此配置可以不写) client.auth("123456"); //查找 client.select("15", function (error) {  if (error) {  console.log(error);  } else {  client.set("node_redis_key", JSON.stringify({ "name": "wolfy", age: 28 }), function (error, res) {  if (error) {  console.log(error);  } else {  console.log(res);  };  //操作完成,关闭redis连接  client.end(true);  });  }; }); 

查询

总结

操作redis的这里只列举添加和查询的,其他的可以自己进行尝试,方法类似。

二 : node.js api解读之file system模块

  1. fs.rename(path1, path2, [callback]),fs.renameSync(path1, path2)
      重命名某个文件,前者异步调用,后者同步调用。(www.61k.com)除非回调函数执行过程出现了异常,否则不会传递任何参数。 例如:

    var fs=require('fs'); fs.rename('D:/test.js','D:/test1.js',function(err){  if(err){  console.log(err); }else{  console.log('renamed complete');  } })

  2. fs.truncate(fd,len,[callback]),fs.trucateSync(fd,len)
     异步调用截断某个文件,如果执行过程中出现异常,回调函数接收一个参数(err),否则不传递任何参数。

    var fs=requrie('fs'); fs.open('../test.js',function(err,fd){  fs.truncate('../test.js',10,function(err){  if(err){  throw err;  }  console.log(fd);  }); });

  3. fs.chmod(path, mode, [callback]) 和 fs.chmodSync(path, mode) 
     修改文件权限,主要说下第二个参数,实际上是:-rwxrwxrwx,三个一组,r:4、w:2、x:1、-: 0。可以 参考 http://zh.wikipedia.org/zh/Chmod

  4. fs.stat(path, [callback]),fs.lstat(path, [callback]),fs.fstat(fd, [callback]) 和 fs.statSync(path)、fs.lstatSync(path)、fs.fstatSync(fd)
    读取文件元信息,回调函数将返回两个参数(err, stats),其中stats是fs.Stats的一个对象.者的区别在于:
    第一个是返回文件的信息,参数是路径
    第二个是和第一个一样,当路径是文件链接时,返回这个链接文件的信息
    第三个是传递参数为fd文件描述符
  5. fs.link(srcpath, dstpath, [callback])、fs.linkSync(srcpath, dstpath) 和 fs.symlink(linkdata, path, [callback])、fs.symlinkSync(linkdata, path)
    建立文件链接,除非回调函数执行过程出现了异常,否则不会传递任何参数。link和symlink的区别是: link 创建的是hard link 所谓硬链接 symlink创建的是symbolic link 所谓符号链接 硬链接就是备份,软连接就是快捷方式
  6. fs.readlink(path, [callback])、fs.realpath(path, [callback]) 、fs.unlink(path, [callback])和 fs.readlinkSync(path)、fs.realpathSync(path)、fs.unlinkSync(path)
    异步调用readlink,回调函数返回两个参数(err,resolvedPath),resolvedPath为解析后的文件路径。 这3个函数分别是: 1、readlink:读取链接源地址 2、realpath:根据相对地址转换为绝对地址 3、unlink:删除某一个文件链接
  7. fs.rmdir(path, [callback])、fs.mkdir(path, mode, [callback])、fs.readdir(path, [callback]) 和 fs.rmdirSync(path)、fs.mkdirSync(path, mode)、fs.readdirSync(path)
    三个命令分别是: rmdir:删除目录 mkdir:建立目录 readdir:读取目录中的内容。回调函数接受两个参数(err, files),其中files参数是保存了目录中所有文件名的数组('.'和'..'除外)。
  8. fs.close(fd, [callback])、fs.closeSync(fd) 和 fs.open(path, flags, [mode], [callback])、fs.openSync(path, flags, [mode])
    fs.open与 C 语言标准库中的 fopen 函数类似。它接受两个必选参数,path 为文件的路径, flags 可以是以下值。 ? r :以读取模式打开文件。
    ? r+ :以读写模式打开文件。
    ? w :以写入模式打开文件,如果文件不存在则创建。
    ? w+ :以读写模式打开文件,如果文件不存在则创建。
    ? a :以追加模式打开文件,如果文件不存在则创建。
    ? a+ :以读取追加模式打开文件,如果文件不存在则创建。
    mode 参数用于创建文件时给文件指定权限,默认是 0666。回调函数将会传递一个文 件描述符 fd。
  9. fs.utimes(path, atime, mtime, callback)、fs.utimesSync(path, atime, mtime) 和 fs.futimes(path, atime, mtime, callback)、fs.futimesSync(path, atime, mtime)
    更改文件时间戳,2者区别在于,utimes更改此文件时间戳,如果此文件指向一个符号链接,futimes更改符号链接的时间戳。
  10. fs.write(fd, buffer, offset, length, position, [callback]) 和 fs.writeSync(fd, buffer, offset, length, position) 和 fs.writeSync(fd, str, position, encoding='utf8')
    fs.write将buffer缓冲器内容写入fd文件描述符,
    offset和length决定了将缓冲器中的哪部分写入文件。
    position指明将数据写入文件从头部算起的偏移位置,若position为null,数据将从当前位置开始写入
    回调函数接受两个参数(err, written),其中written标识有多少字节的数据已经写入
    第三个是基于字符串的fs.write()的同步版本,返回写入数据的字节数。
    注意:写完后要关闭它
  11. fs.read(fd, buffer, offset, length, position, [callback]) 、fs.readSync(fd, buffer, offset, length, position)、fs.readSync(fd, length, position, encoding) 和 fs.readFile(filename, [encoding], [callback])、fs.readFileSync(filename, [encoding])〈br /> 前3个是读取文件描述符和BUFFER的方法,后2个是读取文件全部内容,比如输出html模版,或者css文件等。
    一般来说,除非必要,否则不要使用前3个是读取文件方式读取文件,因为它要求你手动管理缓冲区 和文件指针,尤其是在你不知道文件大小的时候,这将会是一件很麻烦的事情。
    fs.read回调函数接受两个参数,(err, bytesRead),bytesRead返回读取到的字节数。
    fs.readFile的回调函数将传入两个参数(err, data),其中data为文件内容,如果没有设置编码,那么将返回原始内容格式的缓冲器。
  12. fs.writeFile(filename, data, encoding='utf8', [callback]),fs.writeFileSync(filename, data, encoding='utf8')
    对应文件写功能
  13. 〈strong>fs.watchFile(filename, [options], listener),fs.unwatchFile(filename)
    fs.watchFile监听指定文件filename的变化,回调函数listener将在每次该文件被访问时被调用.
    第二个参数[options]是可选项,如果指定了options参数,它应该是一个包含如下内容的对象:名为persistent的布尔值,和名为interval单位为毫秒的轮询时间间隔,默认值为{ persistent: true, interval: 0 }。 listener监听器将获得两个参数(curr, prev),分别标识当前的状态对象和改变前的状态对象,这些状态对象为fs.Stat的实例。
    fs.unwatchFile停止监听文件filename的变化。
  14. fs.Stats
    fs.stat()和 fs.lstat()方法返回的对象为此类型
    • stats.isFile()
    • stats.isDirectory()
    • stats.isBlockDevice()
    • stats.isCharacterDevice()
    • stats.isSymbolicLink() (only valid with fs.lstat()stats.isSymbolicLink() (仅对fs.lstat()有效)
    • stats.isFIFO()
    • stats.isSocket()

      { dev: 2049,  ino: 305352,  mode: 16877,  nlink: 12,  uid: 1000,  gid: 1000,  rdev: 0,  size: 4096,  blksize: 4096,  blocks: 8,  atime: '2009-06-29T11:11:55Z',  mtime: '2009-06-29T11:11:40Z',  ctime: '2009-06-29T11:11:40Z' }

  15. fs.createReadStream(path, [options])
    返回一个新的可读流对象options是包含如下默认值的对象:
    { flags: 'r', encoding: null, fd: null, mode: 0666, bufferSize: 64 * 1024 }
    如果不想读取文件的全部内容,可以在options参数中设置start和end属性值以读取文件中指定范围的内容。start和end包含在范围中(闭集合),取值从0开始。这两个参数需要同时设置。
  16. fs.createWriteStream(path, [options])

    options参数是包含如下默认值的对象:
    { flags: 'w', encoding: null, mode: 0666 }

参考资料:,

三 : Node.js实现的BigPipe

以前用PHP实现过,详情点击这里查看《Nginx中的PHP的缓冲问题》

无论用java、.net还是python都是可以实现bigpipe的…

 

拿那篇文章中的php显示页做示例:

bigpipe Node.js实现的BigPipe

先输出页面的主体结构:

bigpipe Node.js实现的BigPipe

然后按顺序更新页面的内容:

bigpipe Node.js实现的BigPipe

bigpipe Node.js实现的BigPipe

bigpipe Node.js实现的BigPipe

2s后输出header

4s后输出content

6s后输出footer

从加载到显示共消耗约13s (2 + 4 + 6 + 1 ~= 13s),符合预期结果

这个示例的源码(可复制至本地直接运行):

/**
* Created with JetBrains WebStorm.
* User: Meteoric_cry
* Date: 13-4-13
* Time: 上午11:10
* To change this template use File | Settings | File Templates.
*/

var http = require('http');

var server = http.createServer(function(req, res) {

res.writeHead(200, {
'Content-Type' : 'text/html',
'Transfer-Encoding' : 'chunked'
});

res.write([
'<!DOCTYPE html>',
'<html>',
'<head>',
'<meta charset="utf-8">',
'<title>Node.js Bigpipe Demo</title>',
'<style type="text/css">',
' * {margin: 0; padding:0;}',
' body {background-color:#fff;}',
' div{border:2px solid #4F81BD; margin:30px; padding: 10px;}',
' p {word-wrap:break-wrod; word-break:break-all; color: #666;}',
' .red {color: #f00;}',
' .blue {color:blue;}',
' .green {color:green;}',
'</style>',
'<script>',
'var g_startTime = new Date();',
'var g_renderArr = []',
'function render(nodeID,html){',
' g_renderArr.push(new Date())',
' document.getElementById(nodeID).innerHTML=html;',
'}',
'</script>',
'</head>',
'<body>',
'<div id="header"><p>Loading...</p></div>',
'<div id="content"><p>Loading...</p></div>',
'<div id="footer"><p>Loading...</p></div>'
].join('\r\n'));

function out_header() {
res.write("<script type='text/javascript'>render('header', '<p><span class=\"blue\">111111</span></p>');</script>\r\n");

setTimeout(out_content, 4 * 1000);
}

function out_content() {
res.write("<script type='text/javascript'>render('content', '<p><span class=\"red\">222222</span></p>');</script>\r\n");

setTimeout(out_footer, 6 * 1000);
}

function out_footer() {
res.write("<script type='text/javascript'>render('footer', '<p><span class=\"green\">333333</span></p>');</script>\r\n");

setTimeout(out_end, 1 * 1000);
}

function out_end() {

res.write([
'<script>',
'var str = [',
' "start:" + g_startTime.toGMTString(),',
' "header:" + g_renderArr[0].toGMTString() + "-" + (g_renderArr[0] - g_startTime) / 1000,',
' "content:" + g_renderArr[1].toGMTString() + "-" + (g_renderArr[1] - g_renderArr[0]) / 1000,',
' "footer:" + g_renderArr[2].toGMTString() + "-" + (g_renderArr[2] - g_renderArr[1]) / 1000,',
' "end:" + new Date().toGMTString() + "-" + (new Date() - g_renderArr[2]) / 1000 + "-" + (new Date() - g_startTime) / 1000',
'].join("\\n");',
'alert(str);',
'</script>'
].join(''));

res.end("\r\n</body></html>");
}

setTimeout(out_header, 2 * 1000);


}).listen(3002);

 

 

上面是将界面的显示顺序固定写死了,下面将展示一个灵活的动态界面:

bigpipe Node.js实现的BigPipe

bigpipe Node.js实现的BigPipe

bigpipe Node.js实现的BigPipe

扩展:nodejs bigpipe / node bigpipe / nodejs 实现文件下载

先输出6个内容容器,然后构建6个客户端请求,当收到请求数据时直接返回给客户端。[www.61k.com]如果你需要让界面的内容按顺序显示,只需要修改,返回的delay值,比如按索引值的大小进行修改

1: var params = url.parse(request.url, true);
2: var delay = params.query.id * 3000; console.log(delay);

 

这个示例的完整源码:

/**
* Created with JetBrains WebStorm.
* User: zhangyi
* Date: 13-4-23
* Time: 上午10:57
* To change this template use File | Settings | File Templates.
*/
var http = require('http');
var sys = require('sys');
var url = require("url");

http.createServer(function(request, response) {

response.writeHead(200, {"Content-Type" : "text/html"});
response.write("<!Doctype html><html><head>");
response.write("<style type='text/css'>div{border:2px solid #4F81BD; margin:30px; padding: 10px;}</style>");
response.write("<script type=\"text/javascript\">function arrived(id,text) { var b=document.getElementById(id); b.innerHTML = text; }</script>");
response.write("</head><body><div>Progressive Loading");
for(var i = 0; i < 6; i++) {
response.write("<div id='" + i + "'>Loading...</div>");
}
response.write("</div>");


var down = 6;
for (i = 0; i < 6; i++) {
var proxy = http.createClient(2000, "localhost");
var proxyRequest = proxy.request("GET", "/?id=" + i, {"host" : "localhost"});

proxyRequest.addListener('response', function (proxyResponse) {
--down;
proxyResponse.addListener('data', function(chunk) {
response.write(chunk, 'binary');
});
proxyResponse.addListener('end', function() {
if(down == 0) {
response.end();
}
});
});
proxyRequest.end();
}
response.write("</body></html>");

}).listen(8080);

http.createServer(function(request, response) {

var delay = Math.round(Math.random() * 8000);
/*
var params = url.parse(request.url, true);
var delay = params.query.id * 3000; console.log(delay);
*/
setTimeout(function() {
var params = url.parse(request.url, true);
var id = params.query.id;
response.writeHead(200, {"Content-Type" : "text/html"});
var content = "<span>Content of Module " + id + "</span>";
response.write("<script>" +
"arrived('" + id + "', '" + content + "');" +
"</script>");
response.end();
}, delay);
}).listen(2000);

 

上面的示例中并没有像第一个例子一样,显示输出header信息('Transfer-Encoding' : 'chunked'),而浏览器,在response里却看到了,猜测是node.js在输出的时候内部加上去的。

 

bigpipe Node.js实现的BigPipe

 

相比php,node.js内部实现并没有“缓冲池”的功能,都是直接输出,很简单吧…

 

 

本文参考:

node.js搭建bigpipe demo时碰到的雷

BigPipe Done in Node.js

bigpipe-node

BigPipe: Pipelining web pages for high performance

扩展:nodejs bigpipe / node bigpipe / nodejs 实现文件下载

四 : Node.js Web开发实战 2

Node.js Web开发实战 第1周

DATAGURU专业数据分析社区

Node.js Web开发实战 讲师 雷宗民

Cookie原理

Cookie是网站为了辨别用户身份、进行会话跟踪而储存在用户本地终端上的数据。 设置Cookie:

服务端响应头 Set-Cookie: NAME=VALUE; Max-Age=MAXAGE; Expires=DATE; Path=PATH; Domain=DOMAIN_NAME; Secure

有多个Cookie时响应多条 Set-Cookie

读取Cookie:

浏览器端请求头 Cookie: name1=value1; name2=value2; name3=value3;

DATAGURU专业数据分析社区

Node.js Web开发实战 讲师 雷宗民

设置Cookie

res.cookie(name, value [, options]) DATAGURU专业数据分析社区

Node.js Web开发实战 讲师 雷宗民

Cookie相关安全问题

?可能是被故意构造的畸形数据,使用前需要校验

?不要完全信任,比如直接通过 isAdmin=1 来判断是否管理员登录 ?不要存储私密的数据,比如密码的MD5值

?使用 httpOnly 来避免跨站攻击

?设置正确的 domain

DATAGURU专业数据分析社区

Node.js Web开发实战 讲师 雷宗民

Cookie使用建议

?每次请求都会带上这些Cookie,所以不宜存储过多的数据(减少流量) ?有些Web服务器对请求头的大小有限制,比如Apache默认为8190字节

DATAGURU专业数据分析社区

Node.js Web开发实战 讲师 雷宗民

Session原理

?辨别用户身份,会话跟踪,数据一般存储在服务器

?一般需要cookie来存储一个Session ID,服务器根据Session ID来查询出详细的Session数据

DATAGURU专业数据分析社区

Node.js Web开发实战 讲师 雷宗民

DATAGURU专业数据分析网站

7

五 : 如何看待 TJ 宣布退出 Node.js 开发,转向 Go?

[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?
参见: Farewell Node.js

下面就看看www.61k.com小编为您搜集整理的参考答案吧。

网友我这是好的[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:
蟹妖。

TJ何许人也?

他medium自我介绍:TJ Holowaychuk,程序员兼艺术家,Koa、Co、Express、jade、mocha、node-canvas、commander.js等知名开源项目的创建和贡献者。

社区影响:

https://nodejsmodules.org第一页出现次数最多的那个少年
Quora: How is TJ Holowaychuk so insanely productive?—高产到令人发指,Quora上甚至有人猜测TJ不是一个人,而事实上他就是一个人。
substack/npmtop:对node npm社区代码贡献截止目前占到整个社区的3.04%

rank percent packages author---- ------- -------- ------# 1 3.04 % 28 tjholowaychuk# 2 2.82 % 26 samuraijack# 3 2.28 % 21 gozala# 4 1.95 % 18 creationix# 5 1.85 % 17 isaacs# 6 1.74 % 16 substack# 7 1.63 % 15 kriskowal# 8 1.52 % 14 marak# 9 1.41 % 13 coolaj86# 9 1.41 % 13 pkrumins# 11 1.19 % 11 masylum# 12 1.09 % 10 TooTallNate# 13 0.98 % 9 cloudhead# 13 0.98 % 9 davglass# 13 0.98 % 9 indexzero


网友蒙面大侠[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:
TJ是个理性的工程师,语言只是工具,什么工具干什么事情,他在告别node的文章中也说了,如果web开发他还是会用node,只不过现在他要转向分布式系统的开发了,所以选择了更加适合的工具golang,这没有什么好奇怪的啊,如果你老板现在突然让你做嵌入式开发你能不转c和汇编吗?


网友程墨Morgan[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:
技术选择,一定不能“哪个61阅读友张明锋[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:
我就纳闷了为什么同样Python twisted也是异步处理就没有大多数技术人员推。好了么,诚如我之前面试时候回答的那样,node.js的callback巨坑而且非coroutine方式处理。我如果需要并行处理的话直接会选择golang连python gevent都不会考虑。


网友蒙面大侠[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:

现在是动态语言一生黑,js缺点前面各位也说了,调试困难调试困难调试困难调试困难调试困难!!!
前后端统一语言没看到什么优点和必要性,在大公司有各种语言实现的基础设施,单node玩不转。甚至go也不好用,现在干活都是在写业务逻辑,用node/go节省不了什么时间,而且那么多周边设施:db proxy /cache service/其他部门外部接口,挨个移植到node、go直至好用实在不容易.

异步callback太难用啦,想想要为每个业务写回调函数就觉得累,逻辑被拆得支离破碎导致阅读困难,代码量更大,RPC才是王道哟。


网友阿哲[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:
JavaScript这个语言设计上的缺陷颇多,并不是最佳的异步服务端编程语言。
前后端统一是个虚幻的优点。实际上前后端的领域知识差异很大,强求统一语言没有必要,就像你不会用C++来写动态页面一样。NodeJS能火,Google的V8功不可没,有干爹就是不一样,想想JavaScript引擎这些年的进步吧。不过Go也是Google的产品,一样有干爹光环。--------------------------------------2014年7月5日更新--------------------------------------------------------------
前后统一,当时提出来的时候我就非常讶异。难道用JavaScript来写后端,就解决现在后端开发的问题了?难道让JavaScript程序员涉及后端,就能降低开发成本?事实是JavaScript并没有什么优势,而且JavaScript程序员的整体水平是比较低的,他们大部分人并不胜任。能用JavaScript在前后端游刃有余的都是牛人,而牛人用其它语言也能干得一样甚至更好,比如投奔Go的这位。


网友lidashuang[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:
一大批Node粉要转Go了


网友刘典[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:
node.js 最大的优势是并发处理能力,不过这个是通过异步方式来达到的,异步方式非常不适合大脑思考,同步模式下简单的逻辑用异步模式来写也要很复杂的代码。go 提供了相同并发性能的同时却可以让程序员以同步方式编写代码。除了遗留系统和学习成本以外实在想不到还继续用 node.js 的理由。


网友洪雁[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:
我只在一个项目中用NodeJS做过服务器,异步编程有的时候真的让人抓心挠肝,TJ向Joyent提出的建议其实每个Node开发者都有感触。

NodeJS开发的易用性上有两点让人特别痛苦:

1. 各种回调方法使得代码非常难以调试;
2. 如果没有一个比较良好的设计,代码乱得一塌糊涂。

但是从目前的发展状况来看,Go语言比较只是Google一家做出贡献,跟Swift、Object C差不多,真正想要像JavaScript一样得到各家公司的认可还需要更多的努力。

微软、Intel还有几家互联网巨头,明显向JavaScript已经抛出了橄榄枝。所以我的观点是:NodeJS只可能越来越好,易用性上社区会注意到,也会不断改善。

more progressive一点的话,Node最好的情形能够像Java一样运行于各类服务器中,最差的可能也就是像python一样,成为在某个方向上的利器。


网友蒙面大侠[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:
虽然,我想写代码写到万万岁,
但是,我觉得我也不会干一辈子程序员的.


网友匿名用户[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:
说真的,TJ没有考虑Scala嘛?


网友匿名用户[koa]如何看待 TJ 宣布退出 Node.js 开发,转向 Go?给出的答复:
怎么不去投奔Yin语言?纳闷。

本文标题:node.js开发实战详解-Node.js操作redis实现添加查询功能
本文地址: http://www.61k.com/1097241.html

61阅读| 精彩专题| 最新文章| 热门文章| 苏ICP备13036349号-1