Node基础知识点--学习笔记(一)
2015-04-18 21:04 龙恩0707 阅读(3006) 评论(0) 编辑 收藏 举报一:建立http服务器;
在D盘建立一个文件夹node,放入app.js,代码如下:
var http = require('http'); http.createServer(function(req,res){ res.writeHead(200,{'Content-type':'text/html'}); res.write("<h1>Node.js</h1>"); res.end("<p>Hello worldA</p>"); }).listen(3000); console.log("11111");
进入D盘node文件下,使用命令 node app.js 即可输出11111,接着在浏览器端我们输入 127.0.0.1:3000 刷新即可看到浏览器下 打印出 Node.js 和 Hello worldA的文案;
上面的程序调用了nodeJS提供的http模块,对所有http请求答复同样的内容监听了3000端口,在终端运行这个脚本发现并没有退出,而是一直等待,这是因为创建了事件监听器;我们还发现如果我们修改了app.js代码后,需要重新运行下node app.js就可以在浏览器端刷新下就可以看到效果,而不是像php一样,修改了下直接可以看效果,这是因为nodejs只有在第一次引用到某部分时才会去解析脚本文件,以后直接都会去访问内存,避免重复执行,而php不同,因为他总是读取并执行脚本,nodejs相比较,性能是提高了,但是对于开发者不方便调试,因此supervisor可以帮助我们实现这个功能;首先我们需要安装supervisor;安装如下:
现在我们可以使用supervisor命令来运行app.js哦!
进入对应目录后 执行supervisor app.js 也可以执行。之后我们修改代码后,直接刷新下浏览器就可以看到效果了!
二:定时器setTimeout(),setInterval(), process.nextTick()及setImmediate()之间的区别;
- setTimeout()与setInterval()和浏览器的api是一样的,分别用于单次和多次定时执行任务。调用setTimeout()与setInterval()创建的定时器会被插入到定时器观察者内部的一个红黑树中,每次Tick执行时候,会从该红黑树中迭代取出定时器对象,检查是否超过定时时间,如果超过,就形成一个事件,它的回调函数将会被执行,但是setTimeout()与setInterval()的缺点是:不精确,不准确,比如说setTimeout()或者setInterval()设定一个任务是5毫秒后执行,但是呢在执行4毫秒后,有一个任务也占了5毫秒的cpu时间片,再次轮到定时器执行时候,时间就已经过期了4毫秒了。
- process.nextTick(), 每次执行process.nextTick()时候,它会将回调函数放入到事件队列中,也就是有一个回调函数,在下一次执行Tick时候,将回调函数取出再执行,执行效率是最高的。
- setImmediate(); 此方法和process.nextTick()方法一样,都是将回调函数延迟执行;
比如如下代码:
process.nextTick(function(){ console.log('nextTick延迟执行'); }); setImmediate(function(){ console.log("setImmediate延迟执行"); }); console.log("正常执行"); 其执行结果如下: 正常执行 nextTick延迟执行 setImmediate延迟执行
从上面可以看到,process.nextTick()中的回调函数的执行优先级高于setImmediate(). 因为事件循环对观察者的检查是有先后顺序的,procee.nextTick()属于ide观察者,setImmediate()属于check观察者。在每一个循环中,ide观察者优先于check观察者。
但是在具体实现上,process.nextTick()的回调函数保存在一个数组中,setImmediate()的结果保存在链表中。在行为上,process.nextTick()在每轮循环中都会将数组中的回调函数全部执行完,而setImmediate()在每轮循环中是执行链表中的一个回调函数。如下代码:
// 加入2个nextTick()的回调函数 process.nextTick(function(){ console.log('nextTick延迟执行1'); }); process.nextTick(function(){ console.log('nextTick延迟执行2'); }); // 加入2个setImmediate()的回调函数 setImmediate(function(){ console.log("setImmediate延迟执行1"); // 进入下次循环 process.nextTick(function(){ console.log('强势插入'); }); }); setImmediate(function(){ console.log("setImmediate延迟执行2"); }); console.log("正常执行"); // 其执行结果如下: nextTick延迟执行1 nextTick延迟执行2 setImmediate延迟执行1 强势插入 setImmediate延迟执行2
从上面的结果可以看出,当第一个setImmediate()的回调函数执行完,并没有立即执行第二个,而是进入了下一轮循环,再次按process.nextTick()优先,setImmediate()的顺序执行。之所以这样设计,是为了保证每轮循环能够较快地执行结束,防止cpu占用过多而阻塞后续的I/O.
4. 使用require.resolve函数查询完整模块名;
首先我们在node文件夹目录下新建app.js, 内容如下:
var str = "aaa";
export.str = str;
定义一个变量,使用export导出变量,供其他模块调用,然后再在相同的目录下新建一个test.js;内容如下:
console.log(require.resolve('./app.js'));
接着我们进入node文件夹目录下,执行test.js代码,如下命令:
可以看到使用require.resolve方法可以打印出模块的完整的路径名。
5. require.cache 对象
在node.js中,定义了一个require.cache对象,该对象代表缓存了所有已被加载模块的缓存区;
我们现在还是以上面的test.js为例:代码改成如下:
//console.log(require.resolve('./app.js'));
console.log(require.cache);
接着我们如下运行代码可以看到我们的缓冲区如下:
6. __filename变量与__dirname变量。
在node.js中,预定义了2个变量,用于获取当前模块文件名的__filename变量与用于获取当前目录名的__dirname变量;
1. __filename变量。
在任何模块文件内部,可以使用__filename变量获取当前模块文件的带有完整绝对路径的文件名。
还是上面node文件内,其中在app.js内代码改成如下:
var testMoudle = require('./test.js');
然后在test.js代码内改成如下:
console.log(__filename);
运行结果如下:
2. __dirname变量。
在任何模块文件内部,可以使用__dirname变量获取当前模块文件所在目录的完整绝对路径。
还是上面node文件内,其中在app.js内代码改成如下:
var testMoudle = require('./test.js');
然后在test.js代码内改成如下:
console.log(__dirname);
运行结果如下:
7. 事件处理机制及事件循环机制。
EventEmitter类的各种方法;
方法名与参数 | 含义 |
addListener(event,listener) | 对指定事件绑定事件处理函数 |
on(event,listener) | addListener方法的别名 |
once(event,listener) | 对指定的事件执行一次的处理函数 |
removeListener(event,listener) | 对指定事件解除事件的处理函数 |
removeAllListeners([event]) | 对指定的事件解除所有的事件处理函数 |
setMaxListeners(n) | 指定事件处理函数的最大数量。 |
listeners(event) | 获取指定事件的所有事件处理函数 |
emit(event,[arg1],[arg2]) | 手工触发指定事件 |
下面我们来看看使用on(或者addListener)方法绑定的事件处理函数;
在node文件夹内中的test.js改为下面的代码
// 使用on方法绑定事件处理函数 var http = require('http'); var server = http.createServer(); server.on('request',function(req,res){ console.log(req.url); res.end(); }); server.listen(1337);
然后执行node test.js 运行如下:
可以看到控制台输出了两个目标的url地址,其中第一个url地址为用户输入的客户端请求的目标url地址,”/” 代表用户输入的目标url地址为web应用程序的根目录,第二个目标url地址为浏览器为页面在收藏夹中的显示图标(默认为favicon.ico)而自动发出请求的目标url地址,但是我们把代码写成如下可以屏蔽收藏夹的请求。
var http = require('http'); var server = http.createServer(); server.on('request',function(req,res){ if(req.url !== '/favicon.ico') { console.log(req.url); } res.end(); }); server.listen(1337);
如下所示:
我们还可以通过多个on方法的执行对同一个事件绑定多个事件处理函数,代码如下:
var http = require('http'); var server = http.createServer(); server.on('request',function(req,res){ if(req.url !== '/favicon.ico') { console.log('接收到客户端请求。'); } }); server.on('request',function(req,res){ if(req.url !== '/favicon.ico') { console.log(req.url); } res.end(); }); server.on('request',function(req,res){ if(req.url !== '/favicon.ico') { console.log('发送响应完毕!'); } res.end(); }); server.listen(1337);
运行效果如下:
2. 自定义事件并将其触发;
// 自定义事件并将其触发 var http = require('http'); var server = http.createServer(); server.on('customEvent',function(arg1,arg2,arg3){ console.log('自定义事件被触发'); console.log(arg1); console.log(arg2); console.log(arg3); }); server.emit('customEvent','自定义参数1','自定义参数2','自定义参数3'); server.listen(1337);
执行如下:
3. 获取指定事件的事件处理函数的数量.
EventEmitter类自身拥有一个listenerCount方法,可用来获取某个对象的指定事件的事件处理函数的数量。代码如下:
EventEmitter.listenerCount(emitter,event);
在listenerCount方法中,使用2个参数,其中第一个参数用于指定需要获取那个对象的事件处理函数的数量,第二个参数用于指定需要获取那个事件的处理函数的数量。
代码如下:
var http = require('http'); var events = require('events'); var server = http.createServer(); // 为server服务器在接收到客户端请求时触发的request事件绑定多个事件处理函数 server.on('request',function(req,res){ if(req.url !== '/favicon.cio') { console.log('接收到客户端请求'); } }); server.on('request',function(req,res){ if(req.url !== '/favicon.cio') { console.log(req.url); } res.end(); }); server.on('request',function(req,res){ if(req.url !== '/favicon.cio') { console.log('发送响应完毕'); } }); server.listen(1337); console.log(events.EventEmitter.listenerCount(server,'request'));
执行如下:
4. EventEmitter类自身所拥有的事件。
在events模块中,为EventEmitter类本身定义了2个事件,newListener事件与removeListener事件。任何时候,当对继承了EventEmitter类的子类实列对象绑定事件处理函数时,都将触发EventEmitter类的newListener事件。如下代码:
var http = require('http'); var server = http.createServer(); server.on('removeListener',function(e,f){ console.log("对"+e+"事件取消事件的处理函数"); console.log(f); }); server.on('newListener',function(e,f){ console.log("对"+e+"事件添加事件的处理函数"); console.log(f); }); var testFunction = function(){ // 为server服务器在接收到客户端请求时触发的request事件绑定多个事件处理函数 server.on('request',function(req,res){ if(req.url !== '/favicon.cio') { console.log('接收到客户端请求'); } }); server.on('request',function(req,res){ if(req.url !== '/favicon.cio') { console.log(req.url); } res.end(); }); server.on('request',function(req,res){ if(req.url !== '/favicon.cio') { console.log('发送响应完毕'); } }); }; server.on('request',testFunction); server.removeListener('request',testFunction); server.listen(1337);
运行如下:
5. 在Node.js中使用调试器。
在node.js中,提供了一个在命令行界面中可以使用的调试器,可以利用该调试器来进行一些应用程序的简单调试,列如显示代码,变量及函数的返回值。
一:在命令行窗口中使用调试器;
在命令行窗口中,可以使用node debug 命令来启用调试器,代码如下所示:
node debug <需要被执行的脚本文件名>
比如现在在app.js加入如下JS代码:
console.log("hello world"); function foo() { console.log("hello foo"); return 100; } var bar = 'this is a pen.'; var http = require('http'); var i = foo(); console.log(i);
截图如下:
然后在命令行中使用 node debug 命令调试该脚本文件,如下:
如果我们想要继续执行下面的代码,我们可以在debug命令后输入 “cont”命令或 ”c”命令(“continue”命令的缩写),以继续执行剩余脚本。如下所示:
但是如果我们不需要执行完剩余的所有脚本代码,我们可以在 ”debug”命令后输入”next”命令或”n” 命令,将程序执行到下一句可执行代码之前。如下所示:
但是如果我们想要进入函数内部的话,我们可以在上面的debug后面输入”step”命令或”s”命令,程序将会暂停在函数内第一行代码之前。如下图所示:
比如JS代码先把require js去掉 如下代码:
console.log("hello world"); function foo() { console.log("hello foo"); return 100; } var bar = 'this is a pen.'; //var http = require('http'); var i = foo(); console.log(i);
执行如下:
当使用”step”命令或”s”命令进入函数内部后,可以继续使用 ”next”命令或”n” 命令逐句执行函数内部的每一行代码,如下图所示:
在函数内部代码被逐句执行的时候,我们可以使用 “out”命令或”o” 命令立即执行完函数内剩余的所有代码,程序将被暂停在调用函数的代码之后的下一句代码之前。如下图所示:
等等,书上还有很多命令,我这边就忽略了,我想现在我们可以来学习一下使用更好的一款调式工具---node-inspector ,它通过web网页与用户进行交互,比node.js中自带的调式器更美观,更方便。
首先我们需要安装node-inspector,
1. 在命令行窗口中输入如下命令
npm install –g node-inspector 如下所示:
看到如上信息,说明已经安装成功,如果安装不成功的话,也不要急,重新运行下,因为由于网络的原因引起的,所以会导致安装不成功,我们可以测试下是否安装成功,如下命令:
node-inspector 如果出现如下,说明安装成功了!
,在使用node-inspector调试工具进行调试时候,首先在命令行窗口中输入如下所示的命令以调试脚本工具。
node --debug-brk[=port] filename
比如我现在的demo,我现在要进入我D盘文件夹node内,调试app.js,那么我需要进入node文件夹内,输入如上的命令来打开调试工具;如下命令:
node --debug-brk[=port] app.js
如下:
接着我们需要打开第二个命令行窗口执行 node-inspector命令以启动调试工具,如下所示:
接着我们需要在浏览器地址栏中输入http://127.0.0.1:8080/debug?port=5858 网址及端口号(8080用于指定node-inspector的web端口,port=5858用于指定node-inspector的调试端口,我们也可以在node-inspector安装目录下的config.json文件中修改node-inspector的web端口和调试端口。)
打开浏览器如下图所示: