最近学习的 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 或者 :
cd /opt/node/bin/
for i in *
do ln -s /opt/node/bin/$i /usr/bin/$i
done // 改成淘宝镜像 后续就可以使用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');

 

posted @ 2018-08-07 17:08  枫若雪  阅读(1449)  评论(0编辑  收藏  举报