模块系统

创建模块

  • mod1.js
1
2
3
exports.say = function(val){
    console.log("say : "+val);
};
  • mod2.js
1
2
3
4
5
6
7
8
9
10
function Hello() {
    var num;
    this.add = function (val) {
        num = val;
    };
    this.say = function () {
        console.log("hello : " + num);
    };
};
module.exports = Hello;
  • main.js
1
2
3
4
5
6
7
8
var mod1 = require("./mod1");
var Hello = require("./mod2");

mod1.say("hello!");

var mod2 = new Hello();
mod2.add(12);
mod2.say();

模块调用规则

原生模块缓存 -> 原生模块目录 -> 文件模块缓存 -> 文件模块目录

函数参数

1
2
3
4
5
6
7
8
9
function say(word) {
  console.log(word);
}

function execute(someFunction, value) {
  someFunction(value);
}

execute(say, "Hello");

匿名函数

1
2
3
4
5
6
7
8
function execute(someFunction, value) {
  someFunction(value);
}

execute(function(word){
    console.log(word)
    },
    "Hello");

路由

  • 用到两个模块

url 分析地址 querystring 解析参数

手册 https://nodejs.org/api/url.html https://nodejs.org/api/querystring.html

  • router.js
1
2
3
exports.route = function (pathName) {
    console.log("route : " + pathName);
};
  • server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var http = require("http");
var url = require("url");

function start(route) {
    function onRequest(request, response) {
        var pathname = url.parse(request.url).pathname;
        console.log("Request for " + pathname + " received.");

        route(pathname);

        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;
  • main.js
1
2
3
4
var server = require("./server");
var router = require("./router");

server.start(router.route);
  • 运行
1
$ node main.js

浏览器输入 http://127.0.0.1:8888/

  • 输出
1
2
3
Server has started.
Request for /%EF%BC%8C%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%E5%A6%82%E4%B8%8B%EF%BC%9A received.
route : /%EF%BC%8C%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%E5%A6%82%E4%B8%8B%EF%BC%9A

代码

https://github.com/hans007/JavaScriptCodes/tree/master/nodejs-do

我的博客

Read More

手册

https://nodejs.org/api/globals.html https://nodejs.org/api/console.html https://nodejs.org/api/process.html https://nodejs.org/api/util.html

全局对象与全局变量

1
__filename
当前正在执行的脚本的文件名

执行

1
console.log( __filename );

输出

1
2
$ node main.js
/code/nodejs/main.js

1
__dirname
当前执行脚本所在的目录

执行

1
console.log( __dirname );

输出

1
2
$ node main.js
/code/nodejs

1
setTimeout(cb, ms) 
只执行一次指定函数

执行

1
2
3
4
5
function printHello(){
   console.log( "Hello, World!");
}
// 两秒后执行以上函数
setTimeout(printHello, 2000);

输出

1
2
$ node main.js
Hello, World!

1
clearTimeout(t)
清除定时器

执行

1
2
3
4
5
6
7
8
function printHello(){
   console.log( "Hello, World!");
}
// 两秒后执行以上函数
var t = setTimeout(printHello, 2000);

// 清除定时器
clearTimeout(t);

输出

1
$ node main.js

1
setInterval(cb, ms)
会不停地调用函数

执行

1
2
3
4
5
function printHello(){
   console.log( "Hello, World!");
}
// 两秒后执行以上函数
setInterval(printHello, 2000);

输出

1
2
3
4
5
6
$ node main.js
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!

1
clearInterval(t)
函数来清除定时器

执行

1
2
3
...
var t = setInterval(printHello, 2000);
clearInterval(t);

输出

1
$ node main.js

1
console
控制台标准输出

方法 描述
console.log([data][, …]) 向标准输出流打印字符并以换行符结束。该方法接收若干 个参数,如果只有一个参数,则输出这个参数的字符串形式。如果有多个参数,则 以类似于C 语言 printf() 命令的格式输出。
console.info([data][, …]) P该命令的作用是返回信息性消息,这个命令与console.log差别并不大,除了在chrome中只会输出文字外,其余的会显示一个蓝色的惊叹号。
console.error([data][, …]) 输出错误消息的。控制台在出现错误时会显示是红色的叉子。
console.warn([data][, …]) 输出警告消息。控制台出现有黄色的惊叹号。
console.dir(obj[, options]) 用来对一个对象进行检查(inspect),并以易于阅读和打印的格式显示。
console.time(label) 输出时间,表示计时开始。
console.timeEnd(label) 结束时间,表示计时结束。
console.trace(message[, …]) 当前执行的代码在堆栈中的调用路径,这个测试函数运行很有帮助,只要给想测试的函数里面加入 console.trace 就行了。
console.assert(value[, message][, …]) 用于判断某个表达式或变量是否为真,接手两个参数,第一个参数是表达式,第二个参数是字符串。只有当第一个参数为false,才会输出第二个参数,否则不会有任何结果。

执行

1
2
3
4
5
6
7
8
// 程序运行耗时
console.time("程序运行耗时");
console.log('Hello world'); 
console.log('byvoid%diovyb'); 
console.log('byvoid%diovyb', 1991);
console.trace()
console.timeEnd('程序运行耗时');
console.info("程序执行完毕。")

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Hello world 
byvoid%diovyb 
byvoid1991iovyb
Trace
    at Object.<anonymous> (/Users/nodejs-do/09-全局对象与变量/main.js:30:9)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Function.Module.runMain (module.js:441:10)
    at startup (node.js:134:18)
    at node.js:962:3
程序运行耗时: 22ms
程序执行完毕。

1
process
是一个全局变量,即 global 对象的属性。

事件 描述
exit 当进程准备退出时触发
beforeExit 当 node 清空事件循环,并且没有其他安排时触发这个事件。通常来说,当没有进程安排时 node 退出,但是 ‘beforeExit’ 的监听器可以异步调用,这样 node 就会继续执行。
uncaughtException 当一个异常冒泡回到事件循环,触发这个事件。如果给异常添加了监视器,默认的操作(打印堆栈跟踪信息并退出)就不会发生。
Signal 事件 当进程接收到信号时就触发。信号列表详见标准的 POSIX 信号名,如 SIGINT、SIGUSR1 等。

执行

1
2
3
4
5
6
7
8
9
10
process.on('exit', function(code) {

  // 以下代码永远不会执行
  setTimeout(function() {
    console.log("该代码不会执行");
  }, 0);

  console.log('退出码为:', code);
});
console.log("程序执行结束");

输出

1
2
3
$ node main.js
程序执行结束
退出码为: 0

退出状态码

名称 描述
Uncaught Fatal Exception 有未捕获异常,并且没有被域或 uncaughtException 处理函数处理。
Unused 保留
Internal JavaScript Parse Error JavaScript的源码启动 Node 进程时引起解析错误。非常罕见,仅会在开发 Node 时才会有。
nternal JavaScript Evaluation Failure JavaScript 的源码启动 Node 进程,评估时返回函数失败。非常罕见,仅会在开发 Node 时才会有。
Fatal Error V8 里致命的不可恢复的错误。通常会打印到 stderr ,内容为: FATAL ERROR
Non-function Internal Exception Handler 未捕获异常,内部异常处理函数不知为何设置为on-function,并且不能被调用。
Internal Exception Handler Run-Time Failure 未捕获的异常, 并且异常处理函数处理时自己抛出了异常。例如,如果 process.on(‘uncaughtException’) 或 domain.on(‘error’) 抛出了异常。
Invalid Argument 可能是给了未知的参数,或者给的参数没有值。
Internal JavaScript Run-Time Failure JavaScript的源码启动 Node 进程时抛出错误,非常罕见,仅会在开发 Node 时才会有。
Invalid Debug Argument 设置了参数–debug 和/或 –debug-brk,但是选择了错误端口。
Signal Exits 如果 Node 接收到致命信号,比如SIGKILL 或 SIGHUP,那么退出代码就是128 加信号代码。这是标准的 Unix 做法,退出信号代码放在高位。

Process 属性

属性 描述
stdout 标准输出流。
stderr 标准错误流。
stdin 标准输入流。
argv argv 属性返回一个数组,由命令行执行脚本时的各个参数组成。它的第一个成员总是node,第二个成员是脚本文件名,其余成员是脚本文件的参数。
execPath 返回执行当前脚本的 Node 二进制文件的绝对路径。
execArgv 返回一个数组,成员是命令行下执行脚本时,在Node可执行文件与脚本文件之间的命令行参数。
env 返回一个对象,成员为当前 shell 的环境变量
exitCode 进程退出时的代码,如果进程优通过 process.exit() 退出,不需要指定退出码。
version Node 的版本,比如v0.10.18。
versions 一个属性,包含了 node 的版本和依赖.
config 一个包含用来编译当前 node 执行文件的 javascript 配置选项的对象。它与运行 ./configure 脚本生成的 “config.gypi” 文件相同。
pid 当前进程的进程号。
title 进程名,默认值为”node”,可以自定义该值。
arch 当前 CPU 的架构:’arm’、’ia32’ 或者 ‘x64’。
platform 运行程序所在的平台系统 ‘darwin’, ‘freebsd’, ‘linux’, ‘sunos’ 或 ‘win32’
mainModule require.main 的备选方法。不同点,如果主模块在运行时改变,require.main可能会继续返回老的模块。可以认为,这两者引用了同一个模块。

执行

1
2
3
4
5
6
7
8
9
10
11
12
13
// 输出到终端
process.stdout.write("Hello World!" + "\n");

// 通过参数读取
process.argv.forEach(function(val, index, array) {
   console.log(index + ': ' + val);
});

// 获取执行路局
console.log(process.execPath);

// 平台信息
console.log(process.platform);

输出

1
2
3
4
5
6
$ node main.js
Hello World!
0: node
1: /cpde/nodejs/main.js
/usr/local/node/0.10.36/bin/node
darwin

Process 提供了很多有用的方法

方法 描述
abort() 这将导致 node 触发 abort 事件。会让 node 退出并生成一个核心文件。
chdir(directory) 改变当前工作进程的目录,如果操作失败抛出异常。
cwd() 返回当前进程的工作目录
exit([code]) 使用指定的 code 结束进程。如果忽略,将会使用 code 0。
getgid() 获取进程的群组标识(参见 getgid(2))。获取到得时群组的数字 id,而不是名字。注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
setgid(id) 设置进程的群组标识(参见 setgid(2))。可以接收数字 ID 或者群组名。如果指定了群组名,会阻塞等待解析为数字 ID 。注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
getuid() 获取进程的用户标识(参见 getuid(2))。这是数字的用户 id,不是用户名。注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
setuid(id) 设置进程的用户标识(参见setuid(2))。接收数字 ID或字符串名字。果指定了群组名,会阻塞等待解析为数字 ID 。注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
getgroups() 返回进程的群组 iD 数组。POSIX 系统没有保证一定有,但是 node.js 保证有。注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
setgroups(groups) 设置进程的群组 ID。这是授权操作,所有你需要有 root 权限,或者有 CAP_SETGID 能力。注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
initgroups(user, extra_group) 读取 /etc/group ,并初始化群组访问列表,使用成员所在的所有群组。这是授权操作,所有你需要有 root 权限,或者有 CAP_SETGID 能力。注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
kill(pid[, signal]) 发送信号给进程. pid 是进程id,并且 signal 是发送的信号的字符串描述。信号名是字符串,比如 ‘SIGINT’ 或 ‘SIGHUP’。如果忽略,信号会是 ‘SIGTERM’。
memoryUsage() 返回一个对象,描述了 Node 进程所用的内存状况,单位为字节。
nextTick(callback) 一旦当前事件循环结束,调用回到函数。
umask([mask]) 设置或读取进程文件的掩码。子进程从父进程继承掩码。如果mask 参数有效,返回旧的掩码。否则,返回当前掩码。
uptime() 返回 Node 已经运行的秒数。
hrtime() 返回当前进程的高分辨时间,形式为 [seconds, nanoseconds]数组。它是相对于过去的任意事件。该值与日期无关,因此不受时钟漂移的影响。主要用途是可以通过精确的时间间隔,来衡量程序的性能。你可以将之前的结果传递给当前的 process.hrtime() ,会返回两者间的时间差,用来基准和测量时间间隔。

执行

1
2
3
4
5
6
7
8
// 输出当前目录
console.log('当前目录: ' + process.cwd());

// 输出当前版本
console.log('当前版本: ' + process.version);

// 输出内存使用情况
console.log(process.memoryUsage());

输出

1
2
3
4
$ node main.js
当前目录: /code/nodejs
当前版本: v4.3.2
{ rss: 12541952, heapTotal: 4083456, heapUsed: 2157056 }

1
util
常用工具

提供常用函数的集合,用于弥补核心JavaScript 的功能 过于精简的不足。

很多方法已经不推荐使用,详见官方手册。

util.inherits

通过原型复制来实现的。

执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var util = require('util');

// 基类
function Base(){
    this.name = 'base';
    this.say = function(){
        console.log('say:'+this.name);
    };
}
Base.prototype.show = function(){
    console.log('show:'+this.name);
};

// 继承类
function Sub(){
    this.name = 'sub';
}

util.inherits(Sub,Base);

var objSub = new Sub();
//objSub.say();
objSub.show();

输出

1
2
$ node inherits.js
show:sub

只是复制方法函数,但是构造函数内部不复制。 所有如果去掉say() ,报错。

util.inspect

将任意对象转换 为字符串的方法 util.inspect(object,[showHidden],[depth],[colors]) showHidden 是一个可选参数,如果值为 true,将会输出更多隐藏信息。 depth 表示最大递归的层数,如果对象很复杂,你可以指定层数以控制输出信息的多 少。如果不指定depth,默认会递归2层,指定为 null 表示将不限递归层数完整遍历对象。 如果color 值为 true,输出格式将会以ANSI 颜色编码,通常用于在终端显示更漂亮 的效果。 特别要指出的是,util.inspect 并不会简单地直接把对象转换为字符串,即使该对 象定义了toString 方法也不会调用。

执行

1
2
3
4
5
6
7
8
9
10
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, 2, true));

输出

1
2
3
4
5
6
7
8
9
10
11
$ node inspect.js
Person { name: 'byvoid', toString: [Function] }
Person {
  name: 'byvoid',
  toString:
   { [Function]
     [length]: 0,
     [name]: '',
     [arguments]: null,
     [caller]: null,
     [prototype]: { [constructor]: [Circular] } } }

util.format(format[, …args])

格式化输出 %s - 字符串 %d - 数字 %j - 输出 json %% - 输出自定义字符 这里是 ‘%’

执行&输出

1
2
3
4
5
6
7
8
9
10
util.format('%s:%s', 'foo');
// Returns: 'foo:%s'

util.format('%s:%s', 'foo', 'bar', 'baz');
// Returns: 'foo:bar baz'

util.format(1, 2, 3);
// Returns: '1 2 3'

util.deprecate(function, string)

标记函数被弃用

执行

  • deprecate.js
1
2
3
4
5
6
7
const util = require('util');

exports.puts = util.deprecate(function() {
  for (var i = 0, len = arguments.length; i < len; ++i) {
    process.stdout.write(arguments[i] + '\n');
  }
}, 'util.puts: Use console.log instead');
  • main.js
1
2
var obj = require('./deprecate');
obj.puts();

输出

1
2
$ node main.js
util.puts: Use console.log instead

代码

https://github.com/hans007/JavaScriptCodes/tree/master/nodejs-do

我的博客

Read More

本机开发环境

开发工具:Atom

自动提示插件:atom-ternjs

回调函数

新建数据文件 title.txt

1
京东(JD.COM)-综合网购首选-正品低价、品质保障、配送及时、轻松购物!

阻塞方式

  • 新建 readSync.js
1
2
3
4
5
6
var fs = require("fs");

var data = fs.readFileSync("title.txt");

console.log(data.toString());
console.log("--- end ---");
  • 运行
1
node readSync.js
  • 输出
1
2
京东(JD.COM)-综合网购首选-正品低价、品质保障、配送及时、轻松购物!
--- end ---

非阻塞方式

  • 新建 read.js
1
2
3
4
5
6
7
8
9
10
var fs = require("fs");

fs.readFile("title.txt", function(err, data){
  if(err){
    return console.error(err);
  }
  console.log(data.toString());
});

console.log("--- end ---");
  • 运行
1
node read.js
  • 输出
1
2
--- end ---
京东(JD.COM)-综合网购首选-正品低价、品质保障、配送及时、轻松购物!

事件循环

这是整个nodejs的核心,全是异步、全是事件接收、队列处理。

一个用户登录

  • 新建 main.js
1
2
3
4
5
6
7
8
9
10
11
12
var events = require("events");
var eventEmitter = new events.EventEmitter();

var listeneUserLogin = function(name,pwd){
  console.log("用户登录:"+name+pwd);
};

eventEmitter.addListener("userLogin", listeneUserLogin);

eventEmitter.emit("userLogin","hans","123456");

console.log("---end---");
  • 运行&输出
1
$ node main.js
1
2
用户登录:hans123456
---end---

事件类方法

addListener(event, listener)

为指定事件添加一个监听器到监听器数组的尾部。

on(event, listener)

为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数。

once(event, listener)

为指定事件注册一个单次监听器,即 监听器最多只会触发一次,触发后立刻解除该监听器。

removeListener(event, listener)

移除指定事件的某个监听器,监听器 必须是该事件已经注册过的监听器。

removeAllListeners([event])

移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器。

setMaxListeners(n)

默认情况下, EventEmitters 如果你添加的监听器超过 10 个就会输出警告信息。 setMaxListeners 函数用于提高监听器的默认限制的数量。

listeners(event)

返回指定事件的监听器数组。

emit(event, [arg1], [arg2], […])

按参数的顺序执行每个监听器,如果事件有注册监听返回 true,否则返回 false。

类方法 listenerCount(emitter, event)

返回指定事件的监听器数量。

newListener

event - 字符串,事件名称; listener - 处理事件函数 该事件在添加新监听器时被触发。

removeListener

event - 字符串,事件名称 listener - 处理事件函数 从指定监听器数组中删除一个监听器。需要注意的是,此操作将会改变处于被删监听器之后的那些监听器的索引。

error 事件

emitter.emit(‘error’);

代码

https://github.com/hans007/JavaScriptCodes/tree/master/nodejs-do

我的博客

Read More

Buffer

创建 Buffer

1
2
3
var buf1 = new Buffer(10);
var buf2 = new Buffer([10, 20, 30, 40, 50]);
var buf3 = new Buffer("京东(JD.COM)-综合网购首选-正品低价、品质保障、配送及时、轻松购物!", "utf-8");

utf-8 是默认的编码方式,此外它同样支持以下编码:”ascii”, “utf8”, “utf16le”, “ucs2”, “base64” 和 “hex”。

写入缓冲区

语法

1
buf.write(string[, offset[, length]][, encoding])
1
2
3
4
buf3 = new Buffer(256);
len = buf3.write("京东(JD.COM)-综合网购首选-");

console.log("写入字节数 : "+  len);

从缓冲区读取数据

语法

1
buf.toString([encoding[, start[, end]]])
1
console.log(buf3.toString('utf-8',0,6));

将 Buffer 转换为 JSON 对象

1
2
var json = buf3.toJSON();
console.log("转换为 JSON 对象 : "+json);

缓冲区合并

语法

1
Buffer.concat(list[, totalLength])
1
2
3
4
var buffer1 = new Buffer('京东(JD.COM)-综合网购首选-');
var buffer2 = new Buffer('正品低价、品质保障、配送及时、轻松购物!');
var buffer3 = Buffer.concat([buffer1,buffer2]);
console.log("buffer3 内容: " + buffer3.toString());

缓冲区比较

语法

1
buf.compare(otherBuffer);

返回一个数字,表示 buf 在 otherBuffer 之前,之后或相同。

1
2
3
4
5
6
7
8
9
10
11
var buffer1 = new Buffer('ABC');
var buffer2 = new Buffer('ABCD');
var result = buffer1.compare(buffer2);

if(result < 0) {
   console.log(buffer1 + " 在 " + buffer2 + "之前");
}else if(result == 0){
   console.log(buffer1 + " 与 " + buffer2 + "相同");
}else {
   console.log(buffer1 + " 在 " + buffer2 + "之后");
}

拷贝缓冲区

语法

1
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])
1
2
3
4
var buffer1 = new Buffer('ABC');
var buffer2 = new Buffer(3);
buffer1.copy(buffer2);
console.log("拷贝缓冲区 : " + buffer2.toString());

缓冲区裁剪

语法

1
buf.slice([start[, end]])
1
2
3
var buffer1 = new Buffer('京东(JD.COM)-综合网购首选-');
var buffer2 = buffer1.slice(0,6);
console.log("缓冲区裁剪 : " + buffer2.toString());

缓冲区长度

1
console.log("缓冲区长度 : " + buffer1.length);

参考手册

https://nodejs.org/api/buffer.html

Stream

从流中读取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var fs = require("fs");
var data = '';

// 创建可读流
var readerStream = fs.createReadStream('input.txt');

// 设置编码为 utf8。
readerStream.setEncoding('UTF8');

// 处理流事件 --> data, end, and error
readerStream.on('data', function(chunk) {
   data += chunk;
});

readerStream.on('end',function(){
   console.log(data);
});

readerStream.on('error', function(err){
   console.log(err.stack);
});

console.log("程序执行完毕");

写入流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var fs = require("fs");
var data = '京东(JD.COM)-综合网购首选-正品低价、品质保障、配送及时、轻松购物!';

// 创建一个可以写入的流,写入到文件 output.txt 中
var writerStream = fs.createWriteStream('output.txt');

// 使用 utf8 编码写入数据
writerStream.write(data,'UTF8');

// 标记文件末尾
writerStream.end();

// 处理流事件 --> data, end, and error
writerStream.on('finish', function() {
    console.log("写入完成。");
});

writerStream.on('error', function(err){
   console.log(err.stack);
});

console.log("程序执行完毕");

管道流

1
2
3
4
5
6
7
8
9
10
11
12
13
var fs = require("fs");

// 创建一个可读流
var readerStream = fs.createReadStream('input.txt');

// 创建一个可写流
var writerStream = fs.createWriteStream('output.txt');

// 管道读写操作
// 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中
readerStream.pipe(writerStream);

console.log("程序执行完毕");

链式流

  • 压缩
1
2
3
4
5
6
7
8
9
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("文件压缩完成。");
  • 解压缩
1
2
3
4
5
6
7
8
9
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("文件解压完成。");

参考手册

https://nodejs.org/api/stream.html

调试工具

npm install -g devtool

1
$ devtool main.js

参考 http://www.open-open.com/lib/view/open1456741326062.html

代码

https://github.com/hans007/JavaScriptCodes/tree/master/nodejs-do

我的博客

Read More

安装

https://nodejs.org/en/download/ 建议用安装包

  • 命令行方式
1
2
3
4
5
6
7
8
9
10
环境
yum install -y gcc-c++ make
curl --silent --location https://rpm.nodesource.com/setup_6.x | bash -

老版本先删除
yum remove -y nodejs npm

安装
yum -y install nodejs
  • 如果安装冲突 建议删除安装
1
2
3
4
5
yum remove nodejs npm -y

- 清理目录
/usr/local/lib
/usr/local/include
  • 升级
1
2
3
4
5
sudo npm cache clean -f
sudo npm install -g n
sudo n 6.11.00
or
sudo n stable

测试环境 helloword

  • 新建文件 helloword.js
1
console.log("helloword!");
  • 运行
1
$ node helloword.js
  • 输出
1
helloword

创建一个 web server

  • 新建文件 webserver.js
1
2
3
4
5
6
7
var http = require("http")
http.createServer(function(request, response){
  response.writeHead(200,{'content-Type':'text/plain'});
  response.end('hello word!');
}).listen(8888);

console.log('web server is running! http://127.0.0.1:8888/');

1
require
调用
1
http
模块 服务
1
listen
监听在 8888 端口

  • 运行
1
$ node webserver.js
  • 输出

浏览器输入 http://127.0.0.1:8888/

参考

https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/

代码

https://github.com/hans007/JavaScriptCodes/tree/master/nodejs-do

我的博客

Read More

npm包管理

安装模块

输入

1
$ npm install express

install 方式用来安装模块 -g 是全局安装, 不加安装在当前

1
node_modules
目录中

查询已安装的模块

输入

1
$ npm ls -g

卸载模块

1
$ npm uninstall express

更新模块

1
$ npm update express

搜索模块

1
$ npm search express

创建模块

  • 输入
1
npm init
  • 按提示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (02-npm) npm-module
version: (1.0.0) 1.0.0
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /Users/hans/Documents/project/JavaScriptCodes/nodejs-do/02-npm/package.json:

{
  "name": "npm-module",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this ok? (yes) yes
  • 查看
    1
    
    package.json
1
2
3
4
5
6
7
8
9
10
11
{
  "name": "npm-module",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

清空NPM本地缓存

1
$ npm cache clear

使用淘宝 NPM 镜像

  • 方式一: 安装 cnpm
1
$ npm install -g cnpm --registry=https://registry.npm.taobao.org

使用

1
$ cnpm install [name]
  • 方式二: 通过config命令
1
2
npm config set registry https://registry.npm.taobao.org 
npm info underscore (如果上面配置正确这个命令会有字符串response)
  • 方式三: 命令行指定
1
npm --registry https://registry.npm.taobao.org info underscore
  • 方式四: 编辑 ~/.npmrc 加入下面内容
1
registry = https://registry.npm.taobao.org

REPL 交互式命令行

表达式计算

1
2
3
4
5
6
7
8
9
10
11
> x = 7
7
> y = 10
10
> x + y
17
> var yy = _
undefined
> console.log(yy)
17
undefined

自动识别多行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> do {
... x++;
... console.log(x);
... }while(x < 20);
8
9
10
11
12
13
14
15
16
17
18
19
20

常用命令

1
2
3
4
5
6
7
8
9
10
ctrl + c - 退出当前终端。
ctrl + c 按下两次 - 退出 Node REPL。
ctrl + d - 退出 Node REPL.
向上/向下 键 - 查看输入的历史命令
tab 键 - 列出当前命令
.help - 列出使用命令
.break - 退出多行表达式
.clear - 退出多行表达式
.save filename - 保存当前的 Node REPL 会话到指定文件
.load filename - 载入当前 Node REPL 会话的文件内容。

代码

https://github.com/hans007/JavaScriptCodes/tree/master/nodejs-do

我的博客

Read More

前言

fis-plus smarty

技术点

静态资源 id

如有目录 home/static/a.js

资源描述写法如下 home:static/a.js

目录规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|---site
|     |---common #通用子系统
|     |      |---config #smarty配置文件
|     |      |---page #模板页面文件目录,也包含用于继承的模板页面
|     |            └── layout.tpl
|     |      |---widget #组件的资源目录,包括模板组件,JS组件,CSS组件等
|     |      |     └── menu   #widget模板组件
|     |      |     |    └── menu.tpl
|     |      |     |    └── menu.js
|     |      |     |    └── menu.css
|     |      |     └── ui   #UI组件
|     |      |          └── dialog  #JS组件
|     |      |          |    └──dialog.js
|     |      |          |    └──dialog.css
|     |      |          └── reset #CSS组件
|     |      |               └── reset.css
|     |      |---static #非组件静态资源目录,包括模板页面引用的静态资源和其他静态资源
|     |      |---plugin #模板插件目录(可选,对于特殊需要的产品线,可以独立维护)
|     |      |---fis-conf.js #fis配置文件
|     |---module1 #module1子系统
|     |      |---test
|     |      |---config
|     |      |---page
|     |            └── index.tpl
|     |      |---widget
|     |      |---static
|     |      |     └── index #index.tpl模板对应的静态资源
|     |      |          └── index.js
|     |      |          └── index.css
|     |      |---fis-conf.js #fis配置文件

文件命名规则

  • 页面 page
1
2
3
tpl :path_to_module/page/页面名.tpl
 js :path_to_module/page/页面名.js
css :path_to_module/page/页面名.css
  • css 组件
1
2
#widget目录下的css文件皆为css组件,建议存放在widget/ui目录下
css :path_to_module/widget/ui/组件名/组件名.css
  • js 组件
1
2
#widget目录下的js文件皆为js组件,建议存放在widget/ui目录下
js :path_to_module/widget/ui/组件名/组件名.js
  • 模板组件
1
2
3
tpl :path_to_module/widget/组件名/组件名.tpl
 js :path_to_module/widget/组件名/组件名.js
css :path_to_module/widget/组件名/组件名.css
  • smarty 配置文件
1
conf:path_to_module/config/模块名/
  • 配置文件 (fis-conf.js)
1
conf:path_to_module/fis-conf.js
  • smarty 插件
1
插件:path_to_module/plugin/
  • 测试数据 (test)
1
2
tpl:path_to_module/page/模块名/页面名.tpl
data:path_to_module/test/page/页面名.json(或php)

Smarty 三种语言能力

  • require

参数 name , src

1
2
3
require name="common:static/lib/jquery.js"
  或
require src="http://www.baidu.com/cdn/jquery.js"
  • uri

参数 name

1
<script src="uri name="common:static/lib/jquery.js" type="text/javascript"></script>
  • 1
    
    widget_inline

内嵌一些widget模板

最新 Smarty 插件

git clone https://github.com/fex-team/fis-plus-smarty-plugin

后进入 plugin 目录 删除.git 目录

参考

http://oak.baidu.com/fis-plus/document.html#%25E9%2585%258D%25E7%25BD%25AE

我的博客

Read More

前言

标准化输出 cmd 代码

安装插件

1
2
$ sudo npm install -g fis3-hook-cmd
$ sudo npm install -g fis3-hook-commonjs

说明 https://github.com/fex-team/fis3-hook-cmd

实例

项目准备

目录

1
2
3
4
5
6
/src/app/main.js
/src/app/webBanner.js
/src/jquery/jquery-debug.js
/static/sea.js
/index.html
/fis-conf.js

seajs下载 http://seajs.org/docs/#downloads

编写代码

/src/app/main.js

1
2
3
4
5
6
define(function(require) {
    var WebBanner = require('./webBanner.js');

    var banner = new WebBanner('#userName');
    banner.render();
});

/src/app/webBanner.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
define(function(require, exports, module) {

    var $ = require('jquery');

    function WebBanner(container){
        this.container = $(container);
        this.username = "";
    }

    module.exports = WebBanner;

    WebBanner.prototype.render = function() {
        this._init();
        this.container.html(this.username);
        console.log(this.username);
    }

    WebBanner.prototype._init = function() {
        this.username = "hans";
    }

});

/index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script src="./static/sea.js"></script>

<script>
// seajs.config({
//     base: "./src/",
//     alias: {
//         "jquery": "jquery/jquery-debug.js",
//         "$": "jquery/jquery-debug.js"
//     }
// });
seajs.use("app/main");
</script>

<h1 id="userName"></h1>

编译的时候 需要把 seajs.config 注释掉,否则会影响fis编译

配置fis-conf.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 只需要编译 html 文件,以及其用到的资源。
fis.set('project.files', ['*.html', 'map.json']);

fis.match('/src/**/*.js', {
  isMod: true
});

fis.match('/static/sea.js', {
  isMod: false
});

fis.hook('cmd', {
  baseUrl: './src/',
  paths: {
    "jquery": "jquery/jquery-debug.js",
    "$": "jquery/jquery-debug.js"
  }
});

fis.match('::packager', {
    postpackager: fis.plugin('loader', {
      allInOne: {
        includeAsyncs: true,
        ignore: ['/static/sea.js']
      }
    })
  });

编译运行

1
2
$ fis3 release
$ fis3 server start

查看结果

/src/app/main.js

1
2
3
4
5
6
define('src/app/main', ['src/app/webBanner'], function(require) {
    var WebBanner = require('src/app/webBanner');

    var banner = new WebBanner('#userName');
    banner.render();
});

/src/app/webBanner.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
define('src/app/webBanner', ['src/jquery/jquery-debug'], function(require, exports, module) {

    var $ = require('src/jquery/jquery-debug');

    function WebBanner(container){
        this.container = $(container);
        this.username = "";
    }

    module.exports = WebBanner;

    WebBanner.prototype.render = function() {
        this._init();
        this.container.html(this.username);
        console.log(this.username);
    }

    WebBanner.prototype._init = function() {
        this.username = "hans";
    }

});

/index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script src="./static/sea.js"></script>

<script>
seajs.config({
    base: "./",
    alias: {
        "jquery": "jquery/jquery-debug.js",
        "$": "jquery/jquery-debug.js"
    }
});
seajs.use("src/app/main");
</script>

<h1 id="userName"></h1>

这里如果正常运行需要还原配置 seajs.config

代码

https://github.com/hans007/JavaScriptCodes/tree/master/fis3/use-seajs

我的博客

Read More

前言

FIS-PLUS 是基于 FIS,应用于后端是 PHP,模板是 Smarty 的场景。现在被大多数百度产品使用。

手册 http://oak.baidu.com/fis-plus/document.html

安装

安装 nodejs

1
http://nodejs.org/

安装 fis-plus

1
$ sudo npm install -g fis-plus

安装 lights

1
$ sudo npm install -g lights

安装 Java

1
http://java.com/

安装 php-cgi

1
$ brew install php55 --with-cgi

如果提示找不到

1
php55
,执行

1
$ brew tap homebrew/homebrew-php

安装 JAVA 和 php-cgi 是由于 fis-plus 内置了 jetty 服务框架来解析 php 脚本

如果npm很慢,可以修改镜像 国内镜像 –registry=http://r.cnpmjs.org 百度内部可以使用公司内镜像 –registry=http://npm.internal.baidu.com

测试运行

1
$ fisp server start

如果发现错误 checking php-cgi support : unsupported php-cgi environment 安装 XAMPP https://www.apachefriends.org

安装成功后

1
2
3
4
5
6
7
使用zsh
$ echo 'export PATH=/Applications/XAMPP/bin:$PATH' >> ~/.zshrc
$ source ~/.zshrc

使用bash
$ echo 'export PATH=/Applications/XAMPP/bin:$PATH' >> ~/.zshrc
$ source ~/.zshrc

实战

下载代码

https://github.com/fex-team/fis-plus-pc-demo

初始fisp server

1
$ fisp server init

发布

1
2
$ fisp release -r common
$ fisp release -r home

运行

1
$ fisp server start #启动服务器

代码

https://github.com/fex-team/fis-plus-pc-demo

我的博客

Read More

前言

通过脚本标注,声明资源的关系,方便后期打包,界面优化。

在html中声明依赖

1
2
3
4
<!--
    @require demo.js
    @require "demo.css"
-->

在js中声明依赖

1
2
3
4
/**
 * @require demo.css
 * @require list.js
 */

在css中声明依赖

1
2
3
4
/**
 * demo.css
 * @require reset.css
 */

创建一个
1
manifest.json
文件

1
__RESOURCE_MAP__

1
__RESOURCE_MAP__
字符串会被替换成
1
依赖关系
的json字符串

配置
1
fis-conf.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fis.match('*.{js,css}', {
    useHash: true
})

fis.match('**.js', {
    release : '/static/js/$0'
});
fis.match('**.css', {
    release : '/static/css/$0'
});

fis.match('*.html', {
    useMap: true
})

默认依赖支持

1
js
1
css
格式,如果加入
1
html
, 需要设置 useMap = true 的属性

运行 fis3 release

查看 manifest.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
    "res": {
        "demo.css": {
            "uri": "/static/css/demo_f1190ba.css",
            "type": "css",
            "deps": [
                "reset.css"
            ]
        },
        "demo.html": {
            "uri": "/demo.html",
            "type": "html",
            "deps": [
                "demo.js",
                "demo.css"
            ]
        },
        "demo.js": {
            "uri": "/static/js/demo_e793ab4.js",
            "type": "js",
            "deps": [
                "demo.css",
                "list.js"
            ]
        }
    },
    "pkg": {}
}

res 是我们的资源 deps 就是我们要的依赖关系了

代码

https://github.com/hans007/JavaScriptCodes/tree/master/fis3/require

我的博客

Read More