Node基础知识点--学习笔记(一)
一:建立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端口和调试端口。)
打开浏览器如下图所示:
Node基础知识点--学习笔记(一)的更多相关文章
- Java后端高频知识点学习笔记1---Java基础
Java后端高频知识点学习笔记1---Java基础 参考地址:牛_客_网 https://www.nowcoder.com/discuss/819297 1.重载和重写的区别 重载:同一类中多个同名方 ...
- linux基础命令学习笔记(二)
linux基础命令学习笔记(二) 1.kill :终止进程 kill pid (唯一标示一个进程) kill -9 强制终止 kill -15 命令未结束不能终止 # ps aux 查看所有进程 ...
- Node.js知识点学习
Node.js知识点学习 一.基本概念 Node.js,或者 Node,是一个可以让 JavaScript 运行在服务器端的平台.可以说,Node.js开创了javascript模块化开发的先河,早期 ...
- Objective-c基础知识学习笔记
Objective-c基础知识学习笔记(一) 一直有记录笔记的习惯.但非常久没分享一些东西了,正好上半年開始学习IOS了,如今有空写点.因开发须要,公司特意为我们配置了几台新MAC.还让我们自学了2周 ...
- node的重点学习笔记(1)————node
node的重点学习笔记(1)----node 提到node就必须提一下他的npm了,npm是世界上最大的开放源代码的生态系统.通俗来说这就如同亚马逊丛林,要啥物种有啥物种,一个巨大的生态圈,里面有一堆 ...
- Python基础班学习笔记
本博客采用思维导图式笔记,所有思维导图均为本人亲手所画.因为本人也是初次学习Python语言所以有些知识点可能不太全. 基础班第一天学习笔记:链接 基础班第二天学习笔记:链接 基础班第三天学习笔记:链 ...
- ASP.Net开发基础温故知新学习笔记
申明:本文是学习2014版ASP.Net视频教程的学习笔记,仅供本人复习之用,也没有发布到博客园首页. 一.一般处理程序基础 (1)表单提交注意点: ①GET通过URL,POST通过报文体: ②需在H ...
- Python基础教程学习笔记:第一章 基础知识
Python基础教程 第二版 学习笔记 1.python的每一个语句的后面可以添加分号也可以不添加分号:在一行有多条语句的时候,必须使用分号加以区分 2.查看Python版本号,在Dos窗口中输入“p ...
- Coursera台大机器学习基础课程学习笔记1 -- 机器学习定义及PLA算法
最近在跟台大的这个课程,觉得不错,想把学习笔记发出来跟大家分享下,有错误希望大家指正. 一机器学习是什么? 感觉和 Tom M. Mitchell的定义几乎一致, A computer program ...
随机推荐
- Java GC机制详解
垃圾收集 Garbage Collection 通常被称为“GC”,本文详细讲述Java垃圾回收机制. 导读: 1.什么是GC 2.GC常用算法 3.垃圾收集器 4.finalize()方法详解 5. ...
- 一千行 MySQL 学习笔记
Windows服务 -- 启动MySQL net start mysql-- 创建Windows服务 sc create mysql binPath= mysqld_bin_path(注意 ...
- Spring全家桶系列–SpringBoot渐入佳境
//本文作者:cuifuan //本文将收录到菜单栏:<Spring全家桶>专栏中 首发地址:https://www.javazhiyin.com/20913.html 萌新:小哥,我在实 ...
- 线程基础的一些理解(一)(java)
一.多线程的基本概念 线程是指进程中的一个执行场景,也就是执行流程,所以我们首先要聊一聊进程,以及进程和线程的关系 1.什么是进程? 一个进程对应一个应用程序,就像我们在windows系统中启动Wo ...
- HDU3829(KB10-J 二分图最大独立集)
Cat VS Dog Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 125536/65536 K (Java/Others)Total ...
- Codeforces339D(SummerTrainingDay06-A 线段树)
D. Xenia and Bit Operations time limit per test:2 seconds memory limit per test:256 megabytes input: ...
- ES6——TDZ(暂时性死区)
暂时性的死区(Temporal Dead Zone),简写为 TDZ: 只要块级作用域里存在let命令,它所声明的变量就绑定这个区域,不在受外部的影响 let 和 const 声明的变量不会被提升到作 ...
- 【读书笔记】iOS-自动布局
自动布局是一项强大的功能,它允许开发者创建一个单一的用户界面,它会自动调整屏幕大小,方向和本地化,Xcode5中的编辑界面的自动布局功能已经大大增强了.当约束缺失或错误配置时,界面生成器可以修复布局. ...
- IDEA项目搭建二——使用SpringBoot创建Web层
一.编写底层代码 1.demo-common中创建FormatString类 先在默认com.tyh中创建package命名为common 删除自动生成的app.java,在common包下创建新类 ...
- 如何借助 HealthKit 打造一款健身应用?
[编者按]本文作者为 Matthew Maher,文章手把手地介绍了如何借助 HealthKit 建立简单的健身应用,包含诸多代码实例.本文系国内 ITOM 管理平台 OneAPM 编译呈现. 根据新 ...