Node.js

作者: 小凡凡520 | 来源:发表于2019-08-12 17:43 被阅读0次
    一、说明
    1、Node.js 就是运行在服务端的 JavaScript
    2、Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台
    3、Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。
    

    如果我们使用PHP来编写后端的代码时,需要Apache 或者 Nginx 的HTTP 服务器,并配上 mod_php5 模块和php-cgi。

    二、安装

    安装

    三、Node.js 应用的组成部分
    • 引入 required 模块
      我们可以使用 require 指令来载入 Node.js 模块
    • 创建服务器
      服务器可以监听客户端的请求,类似于 Apache 、Nginx 等 HTTP 服务器
    • 接收请求与响应请求
      服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据
    var http = require('http');
    
    http.createServer(function (request, response) {
    
        // 发送 HTTP 头部 
        // HTTP 状态值: 200 : OK
        // 内容类型: text/plain
        response.writeHead(200, {'Content-Type': 'text/plain'});
    
        // 发送响应数据 "Hello World"
        response.end('11111Hello World\n');
    }).listen(8888);
    
    // 终端打印如下信息
    console.log('Server running at http://127.0.0.1:8888/');
    
    四、基本使用

    Node.js REPL(交互式解释器)

    // 表达式:
    $ node
    > 1 +4
    5
    
    // 使用变量
    $ node
    > x = 10
    10
    
    // 多行表达式
    $ node
    > do {
    ... x++;
    ... console.log("x: " + x);
    ... } while ( x < 5 );
    
    // 下划线(_)变量
    $ node
    > var x = 10
    undefined
    > var y = 20
    undefined
    > x + y
    30
    > var sum = _
    undefined
    > console.log(sum)
    30
    

    REPL 命令

    快捷键 说明
    ctrl + c 退出当前终端
    ctrl + c 按下两次 退出 Node REPL
    ctrl + d 退出 Node REPL
    向上/向下 键 查看输入的历史命令
    tab 键 列出当前命令
    .help 列出使用命令
    .break 退出多行表达式
    .clear 退出多行表达式
    .save filename 保存当前的 Node REPL 会话到指定文件
    .load filename 载入当前 Node REPL 会话的文件内容
    五、回调

    同步

    var fs = require('fs');
    var data = fs.readFileSync('/Users/chen_fan/Desktop/mmm.rtf');
    
    console.log(data.toString());
    

    异步

    var fs = require('fs');
    fs.readFile("/Users/chen_fan/Desktop/mmm.rtf",function (err,data) {
        if (err) return;
        console.log(data.toString());
        console.log('2');
    })
    console.log('1');
    
    六、事件循环

    1、Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高
    2、Node.js 几乎每一个 API 都是支持回调函数的。
    3、Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现
    4、Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数

    事件驱动程序

    1、Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。
    2、当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户
    3、这个模型非常高效可扩展性非常强,因为webserver一直接受请求而不等待任何读写操作。(这也被称之为非阻塞式IO或者事件驱动IO)
    在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。
    
    var events = require('events');
    var eventEmitter = new  events.EventEmitter();
    
    var connectHandle = function connected() {
        console.log("连接成功");
    
        eventEmitter.emit('data_received');
    }
    
    eventEmitter.on('connection',connectHandle);
    
    eventEmitter.on('data_received',function() {
        console.log("数据接收成功");
    })
    
    eventEmitter.emit("connection");
    
    console.log('完成')
    
    var EventEmitter = require('events').EventEmitter;
    var event = new EventEmitter();
    event.on('some_event',function () {
      console.log('事件触发');
    });
    setTimeout(function () {
      event.emit('some_event');
    });
    
    var events = require('events');
    var emitter =  new events.EventEmitter();
    emitter.on('some_event',function (v1, v2) {
      console.log(v1 + v2);
    });
    emitter.on('some_event',function (v1, v2) {
      console.log(v1,v2);
    });
    emitter.emit('some_event',1,2);
    
    var events = require('events');
    var emitter = new events.EventEmitter();
    
    var call = function() {
        console.log('add');
    };
    
    emitter.addListener('ss',call);
    
    emitter.removeListener('ss',call);
    
    emitter.emit('ss');
    
    var events = require('events');
    var emitter = new events.EventEmitter();
    
    var listener1 = function () {
        console.log('test1');
    };
    var listener2 = function () {
        console.log('test2');
    };
    
    emitter.addListener('test',listener1);
    emitter.on('test',listener2);
    
    console.log(emitter.listenerCount('test'));
    
    emitter.emit('test');
    
    七、缓冲区
    const buf = Buffer.from('chenfan','ascii');
    console.log(buf.toString('hex'));
    console.log(buf.toString('base64'));
    
    编码 说明
    ascii 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的
    utf8 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8
    utf16le 2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)
    ucs2 utf16le 的别名
    base64 Base64 编码
    latin1 一种把 Buffer 编码成一字节编码的字符串的方式
    binary latin1 的别名
    hex 将每个字节编码为两个十六进制字符
    // 创建一个长度为 10、且用 0 填充的 Buffer。
    const buf1 = Buffer.alloc(10);
    
    // 创建一个长度为 10、且用 0x1 填充的 Buffer。 
    const buf2 = Buffer.alloc(10, 1);
    
    // 创建一个长度为 10、且未初始化的 Buffer。
    // 这个方法比调用 Buffer.alloc() 更快,
    // 但返回的 Buffer 实例可能包含旧数据,
    // 因此需要使用 fill() 或 write() 重写。
    const buf3 = Buffer.allocUnsafe(10);
    
    // 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
    const buf4 = Buffer.from([1, 2, 3]);
    
    // 创建一个包含 UTF-8 字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
    const buf5 = Buffer.from('tést');
    
    // 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
    const buf6 = Buffer.from('tést', 'latin1');
    
    buf1.write('123');
    
    buf1.toString('utf8')
    
    八、流

    读数据

    var fs = require('fs');
    var data = '';
    
    var readerStream = fs.createReadStream('/Users/chen_fan/Desktop/HH.h')
    readerStream.setEncoding('UTF-8');
    
    readerStream.on('data',function (chunk) {
        data += chunk;
    });
    readerStream.on('end',function () {
        console.log(data);
    });
    readerStream.on('error',function (err) {
        console.log(err.stack);
    });
    

    写数据

    var fs = require('fs');
    var data = 'test';
    var writeStream = fs.createWriteStream('/Users/chen_fan/Desktop/mmm.rtf');
    writeStream.write(data,'utf8');
    writeStream.end();
    
    writeStream.on('finish',function () {
        console.log('ok');
    });
    writeStream.on('error',function (err) {
        console.log(err.stack);
    });
    

    管道流

    var fs = require('fs');
    var readStream = fs.createReadStream('/Users/chen_fan/Desktop/mmm.rtf');
    var writeStream = fs.createWriteStream('/Users/chen_fan/Desktop/m1.rtf');
    
    readStream.pipe(writeStream);
    

    链式流

    var fs = require("fs");
    var zlib = require('zlib');
    
    // 压缩 input.txt 文件为 input.txt.gz
    fs.createReadStream('input.txt')
      .pipe(zlib.createGzip())
      .pipe(fs.createWriteStream('input.txt.gz'));
      
    console.log("文件压缩完成。");
    
    var fs = require("fs");
    var zlib = require('zlib');
    
    // 解压 input.txt.gz 文件为 input.txt
    fs.createReadStream('input.txt.gz')
      .pipe(zlib.createGunzip())
      .pipe(fs.createWriteStream('input.txt'));
      
    console.log("文件解压完成。");
    
    九、模块系统

    接口

    exports.world = function() {
        console.log('Hello World');
    };
    
    exports.hh = function () {
        console.log('test');
    }
    
    var hello = require('./hello');
    hello.hh();
    

    模块

    //hello.js
    function Hello() {
        var name;
        this.setName = function(thyName) {
            name = thyName;
        };
        this.sayHello = function() {
            console.log('Hello ' + name);
        };
    };
    module.exports = Hello;
    
    var Hello = require('./hello');
    var hello = new Hello();
    hello.setName('chenfan');
    hello.sayHello();
    
    十、函数

    普通函数

    function say(word) {
        console.log(word)
    };
    
    function test(some, value) {
        some(value);
    };
    
    test(say,'chenfan');
    

    匿名函数

    function test(some, value) {
        some(value);
    }
    
    test(function (word) {
        console.log(word)
    },'chenfan');
    
    var http = require('http');
    
    http.createServer(function (request, response) {
        response.writeHead(200,{'Content-Type':'text/plain'});
        response.write('chenfan');
        response.end();
    }).listen(8888);
    
    var http = require('http');
    
    function onRequest(request,response){
        response.writeHead(200,{'Content-Type':'text/plain'});
        response.write('chenfan');
        response.end();
    }
    
    http.createServer(onRequest).listen(8888);
    
    十一、路由
    // server.js
    var http = require("http");
    var url = require("url");
     
    function start() {
      function onRequest(request, response) {
        var pathname = url.parse(request.url).pathname;
        console.log("Request for " + pathname + " received.");
        response.writeHead(200, {"Content-Type": "text/plain"});
        response.write("Hello World");
        response.end();
      }
     
      http.createServer(onRequest).listen(8888);
      console.log("Server has started.");
    }
     
    exports.start = start;
    
    // router.js
    function route(pathname) {
      console.log("About to route a request for " + pathname);
    }
     
    exports.route = route;
    
    // main.js
    var server = require("./server");
    var router = require("./router");
     
    server.start(router.route);
    
    十二、常用工具
    var util = require('util'); 
    function Base() { 
        this.name = 'base'; 
        this.base = 1991; 
        this.sayHello = function() { 
        console.log('Hello ' + this.name); 
        }; 
    } 
    Base.prototype.showName = function() { 
        console.log(this.name);
    }; 
    function Sub() { 
        this.name = 'sub'; 
    } 
    util.inherits(Sub, Base); 
    var objBase = new Base(); 
    objBase.showName(); 
    objBase.sayHello(); 
    console.log(objBase); 
    var objSub = new Sub(); 
    objSub.showName(); 
    //objSub.sayHello(); 
    console.log(objSub);
    
    var util = require('util'); 
    function Person() { 
        this.name = 'byvoid'; 
        this.toString = function() { 
        return this.name; 
        }; 
    } 
    var obj = new Person(); 
    console.log(util.inspect(obj)); 
    console.log(util.inspect(obj, true)); 
    
    var util = require('util');
    
    util.isArray([])
      // true
    util.isArray(new Array)
      // true
    util.isArray({})
      // false
    
    var util = require('util');
    
    util.isRegExp(/some regexp/)
      // true
    util.isRegExp(new RegExp('another regexp'))
      // true
    util.isRegExp({})
      // false
    
    var util = require('util');
    
    util.isDate(new Date())
      // true
    util.isDate(Date())
      // false (without 'new' returns a String)
    util.isDate({})
      // false
    
    var util = require('util');
    
    util.isError(new Error())
      // true
    util.isError(new TypeError())
      // true
    util.isError({ name: 'Error', message: 'an error occurred' })
      // false
    
    十三、文件系统

    读取文件

    var fs = require("fs");
    
    // 异步读取
    fs.readFile('input.txt', function (err, data) {
       if (err) {
           return console.error(err);
       }
       console.log("异步读取: " + data.toString());
    });
    
    // 同步读取
    var data = fs.readFileSync('input.txt');
    console.log("同步读取: " + data.toString());
    
    console.log("程序执行完毕。");
    

    打开文件

    var fs = require("fs");
    
    // 异步打开文件
    console.log("准备打开文件!");
    fs.open('input.txt', 'r+', function(err, fd) {
       if (err) {
           return console.error(err);
       }
      console.log("文件打开成功!");     
    });
    
    flag 说明
    r 以读取模式打开文件。如果文件不存在抛出异常
    r+ 以读写模式打开文件。如果文件不存在抛出异常
    rs 以同步的方式读取文件
    rs+ 以同步的方式读取和写入文件
    w 以写入模式打开文件,如果文件不存在则创建
    wx 类似 'w',但是如果文件路径存在,则文件写入失败
    w+ 以读写模式打开文件,如果文件不存在则创建
    wx+ 类似 'w+', 但是如果文件路径存在,则文件读写失败
    a 以追加模式打开文件,如果文件不存在则创建
    ax 类似 'a', 但是如果文件路径存在,则文件追加失败
    a+ 以读取追加模式打开文件,如果文件不存在则创建
    ax+ 类似 'a+', 但是如果文件路径存在,则文件读取追加失败

    获取文件信息

    var fs = require('fs');
    
    fs.stat('/Users/liuht/code/itbilu/demo/fs.js', function (err, stats) {
        console.log(stats.isFile());         //true
    })
    
    十四、GET / POST
    var http = require('http');
    var url = require('url');
    var util = require('util');
    
    http.createServer(function(req, res){
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end(util.inspect(url.parse(req.url,true)));
    
    }).listen(3000);
    
    var http = require('http');
    var url = require('url');
    var util = require('util');
    
    http.createServer(function(req, res){
        res.writeHead(200, {'Content-Type': 'text/plain'});
    
        // 解析 url 参数
        var params = url.parse(req.url, true).query;
        res.write("网站名:" + params.name);
        res.write("\n");
        res.write("网站 URL:" + params.url);
        res.end();
    
    }).listen(3000);
    
    var http = require('http');
    var querystring = require('querystring');
    
    var postHTML =
        '<html><head><meta charset="utf-8"><title>菜鸟教程 Node.js 实例</title></head>' +
        '<body>' +
        '<form method="post">' +
        '网站名: <input name="name1"><br>' +
        '网站 URL: <input name="url1"><br>' +
        '<input type="submit">' +
        '</form>' +
        '</body></html>';
    
    http.createServer(function (req, res) {
        var body = "";
        req.on('data', function (chunk) {
            body += chunk;
        });
        req.on('end', function () {
            // 解析参数
            body = querystring.parse(body);
            // 设置响应头部信息及编码
            res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
    
            if(body.name1 && body.url1) { // 输出提交的数据
                res.write("网站名:" + body.name1);
                res.write("<br>");
                res.write("网站 URL:" + body.url1);
            } else {  // 输出表单
                res.write(postHTML);
            }
            res.end();
        });
    }).listen(3000);
    

    相关文章

      网友评论

          本文标题:Node.js

          本文链接:https://www.haomeiwen.com/subject/uxywdctx.html