• 最近学习的 Node.js 基础:安装、环境配置、forever


    最近工作中,因为某某某某原因,需要用到Node.js  。 

    发现在很多方面和python很像,比如generator / yield ,比如模块的使用方式,比如http模块。

    先安装个环境,windows没什么难度,下载个安装包装一下就行,主要看一下centos的

    并且修改了npm源为淘宝源,主要是下载速度快。并且安装了forever组件,作为服务器的 node 服务器守护程序。

    // centos6.5下安装
    
    // 官网下载: https://nodejs.org/en/download/
    // 或者淘宝镜像下载 https://npm.taobao.org/mirrors/node/v8.11.4/
    
    // node-v8.11.4-linux-x64.tar.gz
    // 不建议源码编译, 速度太慢.
    
    tar zxvf node-v8.11.4-linux-x64.tar.gz 
    mv node-v8.11.4-linux-x64 node-v8.11.4

    vim /etc/profile // 添加环境变量
    export NODE_HOME=/opt/node-v8.11.4 
    export PATH
    =$NODE_HOME/bin:$PATH
    // 执行 source /etc/profile
    // 最后执行 node -v 
    // npm -v 
    // 如果这2个命令能正确执行,即安装成功. 
    
    # 今天下载了LTS 的10.16.3,却是个tar.xz
    xz -d node-v10.16.3-linux-x64.tar.xz
    tar xf node-v10.16.3-linux-x64.tar
    mv node-v10.16.3-linux-x64 node
    # 也可以不添加环境变量,使用软连接方式 ln -s /opt/node/bin/node /usr/bin/node ln -s /opt/node/bin/npm /usr/bin/npm ln -s /opt/node/bin/npx /usr/bin/npx // 改成淘宝镜像 后续就可以使用cnpm 命令了. npm install -g cnpm --registry=https://registry.npm.taobao.org // 装个forever 试试 这个一般用于生产环境作为node服务器 cnpm install forever -g

    npm install 可以简写为 npm i 

    npm 的命令很简单易理解。 直接命令 npm 回车,会给出帮助, npm -l 会给出更详细的帮助。 npm <cmd> -h  会给出针对 cmd命令的帮助

    nrm 是一个管理 npm 源的工具。用来切换官方 npm 源和国内的 npm 源(如: cnpm),当然也可以用来切换官方 npm 源和公司私有 npm 源。

    全局安装 nrm:

    npm i nrm -g
    nrm ls   # 查看源列表,有 * 的为当前使用的源
    
    nrm use taobao  # 切换为 taobao 源

    forever的组件简单易用,并且较为稳定。forever可以看做是一个nodejs的守护进程,能够启动,停止,重启我们的app应用。

     Github地址:https://github.com/nodejitsu/forever  不过,看起来,最后的更新都停在2年前了。

    另外一个nodejs守护进程 pm2 一直有更新,可参考此文安装配置使用:https://blog.csdn.net/maquealone/article/details/79550120

    forever    # 显示帮助
    
    forever start app.js   # 简单启动app
    
    # 追加至日志,forever默认是不能覆盖上次的启动日志, // 所以如果第二次启动不加-a,则会不让运行 
    forever start -l forever.log -a app.js   
    
    forever list    # 查看到当前运行的所有服务
    
    forever stopall   # 停止所有运行服务
    
    forever stop app.js    # 停止指定文件服务
    
    forever restart app.js     # 和停止服务方式一样
    forever restartall    # 重启全部

    开始:第一个js

    let time=0;  // 初始化时间为0
    
    // 设置一个定时器, 每隔半秒输出一个内容.
    let tmr = setInterval(function () {
        console.log('aaaaaaaaaaaaaaa ' + time);
        time ++;
        if(time>=5){
            clearInterval(tmr);
        }
    },500);
    
    
    console.log(__dirname); //所在路径
    console.log(__filename);  //完整路径及文件名

    简单的函数示例:

    // // 两种函数的写法
    // function sayHi() {
    //     console.log('hi');
    // }
    //
    // sayHi();
    //
    // let sayBye=function () {
    //     console.log("bye,");
    // }
    //
    // sayBye();
    
    
    
    /* 回调函数 */
    // function callFunc(fun) {
    //     fun();
    // }
    //
    // let sayHello = function(){
    //     console.log("Hello.");
    // }
    //
    // callFunc(sayHello); // 输出Hello.
    
    
    // 带有参数的回调函数
    function callFunc(func,name) {
        func(name);
    }
    
    let sayHello = function (name) {
        console.log('Hello, '+name);
    };
    
    callFunc(sayHello,'Jerry');
    
    
    // 或者这样写
    function foo(fun,name) {
        fun(name);
    }
    
    foo(function (name) {
        console.log(name + ' world.')
    },'Hello');

    自定义简单模块:b03_model_count.js

    let counter = function (arr) {
        return "There are " + arr.length + " elements in array.";
    };
    
    let addr = function (a, b) {
        return a + b;
    };
    
    let pi = 3.14;
    
    // module.exports.cnt = counter;
    // module.exports.add = addr;
    // module.exports.pi = pi;
    
    // 或者写成键值对
    module.exports = {
        cnt:counter,
        add:addr,
        pi:pi
    };

    b03_model_count2.js

    let addr = function (a, b) {
        return a + b;
    };
    
    let pi = 3.1415926;
    
    
    // 或者写成键值对, 但是这样不易阅读
    module.exports = {
        cnt:function (arr) {
            return "There are " + arr.length + " elements in array.";
        },
        add:addr,
        pi:pi,
    };

    b03_model_app.js  这个文件中使用了上面两个自定义的模块。

    let ss = require('./b03_model_count');
    
    let pi = require('./b03_model_count2').pi;
    
    console.log(ss.cnt([1,3,4,5]));
    console.log(ss.add(3,9));
    console.log(ss.pi);
    console.log(pi);

    事件 events

    let events = require('events');
    
    // 创建 eventEmitter 对象
    let testEmiter = new events.EventEmitter();
    
    // 注册事件监听器  事件名是一个字符串,通常表达一定的语义 some_events
    testEmiter.on('some_events',function (msg) {
        console.log(msg,' 执行事件绑定的匿名函数 ');
    });
    
    // on 函数用于绑定事件函数,emit 属性用于触发一个事件。
    testEmiter.emit('some_events',"what the fuck ?");
    
    
    // 参考 http://www.runoob.com/nodejs/nodejs-event.html

    events 例一

    const events = require('events');
    const util = require('util');
    
    let Person = function (name) {
        this.name = name;
    };
    
    // 使用继承工具,让 Person类去继承 events.EventEmitter
    util.inherits(Person, events.EventEmitter);
    
    let alex = new Person('alex');
    let jerry = new Person('jerry');
    let tom = new Person('tom');
    
    // 将三个对象赋给数组
    let ps = [alex, jerry, tom];
    
    // 列表对象的遍历方法
    ps.forEach(function (person) {
        person.on('speak', function (msg) {
            console.log(person.name + " said: " + msg)
        });
    
        person.on('run', function (res) {
            console.log(person.name + ' run ' + res);
        });
    });
    
    // 触发事件
    alex.emit('speak', '第二个参数 msg ');
    jerry.emit('speak', '说什么呢?');
    tom.emit('run', '500m');

    events 例二 

    const events=require('events');
    const util = require('util');
    
    let Person=function(name){
        this.name=name;
    };
    
    util.inherits(Person,events.EventEmitter);
    
    let lucy=new Person("Lucy");
    let jim=new Person("Jim");
    
    let ps=[lucy,jim];
    
    ps.forEach(function (psn) {
        psn.on('say',function (msg) {
            console.log(psn.name + " say: " + msg);
        });
    });
    
    lucy.emit('say',"你制杖吗?");
    jim.emit('say',"不,我贩剑.");

    文件的异步方式与同步方式 读写

    let fs = require('fs');
    
    // 读文件 同步的方法
    // let rs = fs.readFileSync("a.txt",'utf8');
    // console.log(rs);
    
    // 异步读文件
    // let rs = fs.readFile("a.txt","utf8",function (err,data) {
    //     console.log(data);
    // });
    
    // 异步方法
    fs.readFile('a.txt','utf8',function (err,data) {
        // 异步写
        fs.writeFile('d.txt', data, function () {
            console.log('复制成功');
        })
    });
    console.log("finished");

    目录与文件的创建与删除

    let fs = require('fs');
    
    // 创建目录 同步
    // fs.mkdirSync('aaa');
    // 删除目录 同步
    // fs.rmdirSync('aaa');
    
    // 异步方式 创建目录 读文件 写文件
    fs.mkdir('./newdir',function () {
        fs.readFile('a.txt','utf8',function (err,data) {
            fs.writeFile('./newdir/c.txt',data,function () {
                console.log('copy success.');
            });
        });
    });
    // 即使目录存在, 多次执行也不会出错.
    // 嵌套写法难以理解. 会有更好的写法来解决.
    
    
    // 异步删除  先删除文件, 再删除目录. 非空目录则删除不成功.
    fs.unlink('./newdir/c.txt', function () {
        fs.rmdir('./newdir',function () {
            console.log('delete success.')
        });
    });

    数据流 stream  优点是简单方便

    const fs = require('fs');
    
    let myReadStream = fs.createReadStream(__dirname + '/a.txt');
    let myWriteStream = fs.createWriteStream(__dirname + '/c.txt');
    
    
    // myReadStream.setEncoding('utf8');
    //
    // // 读取后直接写入
    // myReadStream.on('data',function (chunk) {
    //     myWriteStream.write(chunk);
    // });
    //
    // myReadStream.on('end',function () {
    //     console.log('copy success.');
    // });
    
    
    // let wd = '你好,这是一个测试.';
    //
    // myWriteStream.write(wd);
    // myWriteStream.end();
    // myWriteStream.on('finish',function () {
    //     console.log('finished.');
    // });
    
    
    // 使用管道一行就搞定
    myReadStream.pipe(myWriteStream);
    const fs = require('fs');
    
    // let myReadStream = fs.createReadStream(__dirname + "/a.txt",'utf8'); // 读取时加上编码
    let myReadStream = fs.createReadStream("./a.txt",'utf8');
    /*
    // myReadStream.setEncoding('utf-8'); // 另外设置编码
    
    myReadStream.on('data', function (chunk) {
        console.log('new chunk received');
        console.log(chunk); // 得到Buffer Buffer满后,会自动创建另一个Buffer, 如果内容过大,会出现多个Buffer
        // console.log(chunk.toString()); // 如果读取时设置了编码,则不必toString()
    });
    */
    
    
    // 如下方法,得到拼接后完整的文件
    let data = "";
    
    myReadStream.on('data', function (chunk) {
        data += chunk;
    });
    
    myReadStream.on('end',function () {
        console.log(data);
    });

    stream例子:

    /**
     * 加密并压缩文档:
     * 但是: 加密之后,压缩率为0
     * 若不加密,压缩率较高
     */
    
    const crypto = require('crypto');
    const fs = require('fs');
    const zlib = require('zlib');
    
    let pwd = new Buffer(process.env.PASS || '123456');
    let encryptStream = crypto.createCipher('aes-256-cbc', pwd); // 加密函数
    
    let gzip = zlib.createGzip(); // 压缩
    let readStream = fs.createReadStream(__dirname + '/a.txt');
    let writeStream = fs.createWriteStream(__dirname + '/out.gz');
    
    // 使用多个管道
    readStream
        .pipe(encryptStream)  // 加密
        .pipe(gzip)           // 压缩 加密之后,压缩率为0
        .pipe(writeStream)    // 写入文件
        .on('finish', function () {
            console.log('done.');
        });

    数据类型

    function show(x) {
    
        console.log(typeof x);    // undefined
        console.log(typeof 10);   // number
        console.log(typeof 'abc'); // string
        console.log(typeof true);  // boolean
    
        console.log(typeof function () {});  //function
    
        console.log(typeof [1, 'a', true]);    //object
        console.log(typeof { a: 10, b: 20 });  //object
        console.log(typeof null);              //object
        console.log(typeof new Number(10));    //object
    }
    show();
    
    
    let fn = function () { };
    // 判断类型
    console.log(fn instanceof Object);  // true
    
    
    // 定义一个函数
    let fnc = function () {
        console.log(100);
    };
    
    // 将若干对象赋给函数的属性
    fnc.a = 10;
    fnc.b = function () {
        alert(123);
    };
    fnc.c = {
        name: "Harry potter",
        year: 2000
    };
    
    fnc();
    console.log(fnc.c);
    function Fn() {
        this.name = 'Harry potter';
        this.year = 2000;
    }
    let fn1 = new Fn();
    console.log(typeof(fn1));               // object
    console.log(fn1 instanceof Object);     // true
    console.log(fn1 instanceof Function);   // false
    
    console.log('-----------------------');
    // var obj = new Object();
    // obj.a = 10;
    // obj.b = 20;
    //
    // var arr = new Array();
    // arr[0] = 5;
    // arr[1] = 'x';
    // arr[2] = true;
    
    
    // 语法糖 比上面写法更简便
    let obj = { a: 10, b: 20 };
    let arr = [5, 'x', true];
    
    console.log(obj instanceof Object);  //true
    console.log(arr instanceof Object);  //true
    
    console.log(typeof(Object)); // function
    console.log(typeof(Array));  // function
    console.log(typeof(obj));  // object
    console.log(typeof(arr));  // object

    字符串转时间:

    var cur_time = '20181112155323';
    var pattern = /(d{4})(d{2})(d{2})(d{2})(d{2})(d{2})/;
    var dd = cur_time.replace(pattern, '$1-$2-$3 $4:$5:$6');
    console.log(dd);

    下面是段乱入的 http server 代码,先不要管它。实现对一个http请求的简单响应。用到3个模块:http, fs 文件,path 路径

    const http = require('http');
    const fs = require('fs');
    const path = require('path');
    //核心模块总是被优先加载,如果它们被require()调用。require('http')将总是返回内建的HTTP模块,即便有一个同名文件存在。
    
    let onReq = function (req, res) {
        console.log('recv a req:');
        res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'});
    
        let wwwdir = path.resolve(__dirname, '../www');
    
        let readStream = fs.createReadStream(wwwdir + '/bbb.html');
        readStream.pipe(res);
    
    };
    
    let server = http.createServer(onReq);
    server.listen(80, '0.0.0.0');
  • 相关阅读:
    Jersey的异常处理
    REST响应处理
    jersey REST的接口简述
    Firebird 同一字段的多行合并为一行
    Firebird/InterBase内置函数使用说明
    发布FireBird数据库所需要DLL文件
    unidac连接FireBird数据库
    打开与关闭Linux防火墙
    Linux FTP 命令
    Linux 命令修改系统时间
  • 原文地址:https://www.cnblogs.com/frx9527/p/nodejs1.html
Copyright © 2020-2023  润新知