nodejs借助于node运行环境而实现的一个比较灵巧的前后一体化的开发环境,随比不了php,python,但是在快速开发维护的时间成本上,node一骑绝尘。node自身由衷的想法,花最小的硬件成本,追求更高的并发,更高的处理性能。
nodejs是一个让javascript运行在服务端的开发平台,它让javascript的触角伸到了服务器,可以与php,jsp,python,ruby平起平坐
node的与众不同之处:
1.node.js不是一门独立的语言,与php,jsp,python, perl,ruby的"既是语言,也是平台"不同,node.js的使用javascript进行编程,运行在chrom的v8引擎之上。它自己不用建设在任何的服务器软件之上。
node特点:
1.单线程
2.非阻塞
3.事件驱动
首先,node不为每一个用户开辟一个线程,所以非常极端的选择了单线程。单线程,要照顾好所有的用户,那么就必须有非阻塞I/O,否则一个人的I/O就把别人,自己的都给阻塞了。一旦有了非阻塞的I/O,一个人如果I/O去了,就会放弃CPU的使用权,换成另一个人使用CPU(或者执行此人后面的语句)。所以CPU的利用率100%。第一个人I/O结束了,就要用事件来通知线程,执行回调函数。此时必须有事件环,就有一个人排队调度机制。Node中有超过半数的C++代码,在搭建事件环
nodejs适合做:
大量的/并发的、网络,文件 I/O
例如,表单提交、考试系统,聊天室,图文直播
不适合做:
由于nodejs善于io不善于计算,复杂的业务逻辑运算
nodejs中回调是优美的实现,这句话没错,但总有些时候我们不想因为异步回调而产生一些不必要的麻烦
存在的问题:
/**
* 需求是遍历某文件夹,只遍历一级(文件或文件夹)中的文件夹,并打印到控制台
*/
let fs = require("fs");
let http = require("http");
// 1.模拟本地服务器
let server = http.createServer(function(req, res){
// 2.规避调由chrome浏览器收藏夹发起的访问的请求
if(req.url == '/favicon.ico'){
return;
}
// 3.读取一个文件夹
fs.readdir('./album', function(err, files){
// 4.声明一个空数组来存放所有的子文件夹
let folderArray = [];
// 此处的就是因为nodejs的回调'太过于无处不在'导致会出现局部变量污染的问题,
// 分析如下:
// 假设files[0]='folder1',
// 试着想一下由于是异步回调,当第一个for循环走完,获取if中的判断还没有执行到,
// 紧接着for走到第二次循环此时files[2]='a.txt',此时if判断恰巧执行到,
// 试问此时的folderArray.push(files[i]);就不是'folder1',而是'a.txt'
// 于是问题就出现了!
for(var i = 0; i < files.length; i ++){
fs.stat('./album/' + files[i], function(err, stats){
if(stats.isDirectory()){
folderArray.push(files[i]);
}
console.log(folderArray);
});
}
console.log(folderArray);
});
res.end();
}).listen(3000, '127.0.0.1');
纠正方案
/**
* 需求是遍历某文件夹,只遍历一级(文件或文件夹)中的文件夹,并打印到控制台
*/
let fs = require("fs");
let http = require("http");
// 1.模拟本地服务器
let server = http.createServer(function(req, res){
// 2.规避调由chrome浏览器收藏夹发起的访问的请求
if(req.url == '/favicon.ico'){
return;
}
// 3.读取一个文件夹
fs.readdir('./album', function(err, files){
// 4.声明一个空数组来存放所有的子文件夹
let folderArray = [];
/**
* 牛x的地方在这里出现,强行将同步变成异步
* -- 自己定义一个函数并且使之立即执行(function method(args){...})(args)
*/
(function iterator(i){
// 5.控制数组下标不越界
if(i == files.length){
// 6.输出满足条件的文件夹
console.log(folderArray);
return;
}
// 7.对files中的元素开始逐一遍历
fs.stat('./album/' + files[i], function(err, stats){
// 8.如果是文件夹则就放入上面预定义的数组内
if(stats.isDirectory()){
folderArray.push(files[i]);
}
// 9. 此处是关键点,也正是这里才是强制同步遍历
iterator(i + 1);
});
})(0);
});
res.end();
}).listen(3000, '127.0.0.1');
这种问题在读数据库时一定要格外注意!!!