zoukankan      html  css  js  c++  java
  • 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()之间的区别;

    1. setTimeout()与setInterval()和浏览器的api是一样的,分别用于单次和多次定时执行任务。调用setTimeout()与setInterval()创建的定时器会被插入到定时器观察者内部的一个红黑树中,每次Tick执行时候,会从该红黑树中迭代取出定时器对象,检查是否超过定时时间,如果超过,就形成一个事件,它的回调函数将会被执行,但是setTimeout()与setInterval()的缺点是:不精确,不准确,比如说setTimeout()或者setInterval()设定一个任务是5毫秒后执行,但是呢在执行4毫秒后,有一个任务也占了5毫秒的cpu时间片,再次轮到定时器执行时候,时间就已经过期了4毫秒了。
    2. process.nextTick(), 每次执行process.nextTick()时候,它会将回调函数放入到事件队列中,也就是有一个回调函数,在下一次执行Tick时候,将回调函数取出再执行,执行效率是最高的。
    3. 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端口和调试端口。)

    打开浏览器如下图所示:

  • 相关阅读:
    第八章 采样
    第七章 优化算法
    第六章 概率图模型
    第五章 非监督学习
    第四章 降维
    第三章 经典算法
    第二章 模型评估
    第一章 特征工程-------------《百面机器学习》
    中等-102,107-二叉树的层序遍历
    字符串单模式匹配 暴力+哈希
  • 原文地址:https://www.cnblogs.com/tugenhua0707/p/4438045.html
Copyright © 2011-2022 走看看