Node.js笔记

Node.js

JavaScript 为客户端而生,Node.js 为网络而生。Node.js 能做的远不止开发一个网 站那么简单,使用 Node.js,你做以下开发:
- 具有复杂逻辑的网站;
- 基于社交网络的大规模 Web 应用;
- Web Socket 服务器;
- TCP/UDP 套接字应用程序;
- 命令行工具;
- 交互式终端程序;
- 带有图形用户界面的本地应用程序;
- 单元测试工具;
- 客户端 JavaScript 编译器。
此外,nodejs还内置了一个HTTP服务器,也即是换锁不要额外的apache来运行。这个服务器不仅可以用来调试代码,而且它本身就可以部署到产品环境,它的性能足以满足要求。值得一提的是node.js还可以调用c/c++的代码。

安装配置Node.js

直接上官网下载安装就是了,winodws和POSIX系统都支持。

源码编译

环境要求

  • c++编译器
  • python
  • libssl-dev 提供 SSL/TLS 加密支持

编译步骤

1.进入源码目录

2.执行./configure

3.执行 make

4.sudo make install

大功告成。

HelloWorld

使用任意的文本编辑器新建一个helloworld.js文件,写入如下的代码:

console.log('Hello World');

终端切换到该js文件所在的目录,运行命令:node HelloWorld.js(不要求一定是.js) 即可打印出Hello World。

Node.js 命令行工具解析

输入node --help

Usage: node [options] [ -e script | script.js ] [arguments]
       node debug script.js [arguments]

Options:
  -v, --version         print Node.js version
  -e, --eval script     evaluate script
  -p, --print           evaluate script and print result
  -c, --check           syntax check script without executing
  -i, --interactive     always enter the REPL even if stdin
                        does not appear to be a terminal
  -r, --require         module to preload (option can be repeated)
  --no-deprecation      silence deprecation warnings
  --trace-deprecation   show stack traces on deprecations
  --throw-deprecation   throw an exception anytime a deprecated function is used
  --no-warnings         silence all process warnings
  --trace-warnings      show stack traces on process warnings
  --trace-sync-io       show stack trace when use of sync IO
                        is detected after the first tick
  --track-heap-objects  track heap object allocations for heap snapshots
  --prof-process        process v8 profiler output generated
                        using --prof
  --zero-fill-buffers   automatically zero-fill all newly allocated
                        Buffer and SlowBuffer instances
  --v8-options          print v8 command line options
  --v8-pool-size=num    set v8's thread pool size
  --tls-cipher-list=val    use an alternative default TLS cipher list
  --use-bundled-ca         use bundled CA store (default)
  --use-openssl-ca         use OpenSSL's default CA store
  --openssl-config=path load OpenSSL configuration file from the
                        specified file (overrides OPENSSL_CONF)
  --icu-data-dir=dir    set ICU data load path to dir
                        (overrides NODE_ICU_DATA)
  --preserve-symlinks   preserve symbolic links when resolving
                        and caching modules.

Environment variables:
NODE_PATH                ':'-separated list of directories
                         prefixed to the module search path.
NODE_DISABLE_COLORS      set to 1 to disable colors in the REPL
NODE_ICU_DATA            data path for ICU (Intl object) data
NODE_NO_WARNINGS           set to 1 to silence process warnings
NODE_PATH               ':'-separated list of directories
                        prefixed to the module search path
NODE_REPL_HISTORY       path to the persistent REPL history file
OPENSSL_CONF            load OpenSSL configuration from file

Documentation can be found at https://nodejs.org/

以上就是node命令的一些说明,例如-v就是查看版本等。可以看到node.jst提供了另一种输出hello world的方式:在终端运行:node -e "console.log('Hello World');" 也可以说输出Hello World

REPL 模式

运行无参数node将会启动一个JavaScript式交互shell

> console.log("Hello world");
Hello world

输入玩你想执行的命令之后按下回车键,Node.js会自动解析并执行命令。

建立http服务器

前面提到过node内置了一个http服务器,那么我们该怎样启用呢?

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write('<h1>Node.js</h1>');
    res.write('<img src="https://ss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=950502116,2213091146&fm=58&u_exp_0=383468501,1879785736&fm_exp_0=86&bpow=1000&bpoh=1500">Node.js</img>');
    res.end('<p>Hello World</p>');
}).listen(3000);
console.log("HTTP server is listening at port 3000.");

然后使用node命令运行就可以使用localhost:3000代开一个页面了。值得注意的是运行之后并不会自动停止,需要按ctrl+c手动停止(有一个坑就是我的macbook输入法没对的时候按ctrl+c是没有反应的)

tips使用supervisor监视代码并重新自动重启

  • 运行命令sudo npm install -g supervisor安装supervisor
  • 使用supervisor 命令运行
    从执行成功然后到更改代码并保存,终端会输入以下内容:
Running node-supervisor with
  program 'HttpServer.js'
  --watch '.'
  --extensions 'node,js'
  --exec 'node'

Starting child process with 'node HttpServer.js'
Watching directory '/Users/xiongyu/Documents/Study/Nodejs' for changes.
Press rs for restarting the process.
HTTP server is listening at port 3000.
crashing child
Starting child process with 'node HttpServer.js'
HTTP server is listening at port 3000.


可以看到supervisor检测到了文件内容发生了变化并重新启动了程序

异步式 I/O 与事件式编程

阻塞与线程

异步式 I/O(AsynchronousI/O)或非阻塞式I/O(Non-blocking I/O)则针对所有I/O 操作不采用阻塞的策略。当线程遇到I/O操作时,不会以阻塞的方式等待I/O操作 的完成或数据的返回,而只是将I/O 请求发送给操作系统,继续执行下一条语句。当操作系统完成 I/O 操作时,以事件的形式通知执行I/O操作的线程,线程会在特定时候处理这个事件。为了处理异步I/O,线程必须有事件循环,不断地检查有没有未处理的事件,依次予以处理。多线程可以让 CPU 资源不被阻塞中的线程浪费。而在非阻塞模式 下,线程不会被 I/O 阻塞,永远在利用 CPU。多线程带来的好处仅仅是在多核 CPU 的情况 下利用更多的核,而Node.js的单线程也能带来同样的好处。

回调函数

看一个读取文件的例子:

var fs=require('fs');
fs.readFile('taylor.txt','utf-8',function (err, data) {
    if (err) { console.error(err);
    } else { console.log(data);
    }
});

console.log('Read File:');

taylor.txt是同级目录下的一个文本文件。运行之后可以看到最先打印出的是:Read File:这一句话,这是因为fs.readFile 调用时所做的工作只是将异步式 I/O 请求发送给了操作系统,然后立即 返回并执行后面的语句,执行完以后进入事件循环监听事件。当 fs 接收到 I/O 请求完成的 事件时,事件循环会主动调用回调函数以完成后续工作。因此我们会先看到 Read File:,再看到 taylor.txt 文件的内容。

事件

把上一个例子改一下来说一下时间

var fs = require('fs');
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter;
fs.readFile('taylor.txt', 'utf-8', function (err, data) {
    if (err) {
        console.error(err);
    } else {
        console.log(data);
        event.emit("readFinsh");
    }
});


event.on("readFinsh", function () {
    console.log("文件读完了");
})

console.log('Read File:');

event对象注册了一个事件readFinsh的监听器,当这个事件执行完之后会像event对象发送事件readFinsh,此时会调用readFinsh的监听器。

Node.js 始终在事件循环中,程序入口就是 事件循环第一个事件的回调函数

模块和包

模块是 Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是 JavaScript 代码、JSON 或者编译过的 C/C++ 扩展

##创建和使用模块
Node.js 提供了 exports 和 require 两个对 象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获 取模块的 exports 对象。

模块的代码:

//ReadFile.js
var fs = require('fs');
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter;


exports.ReadFile = function (fileName) {
    fs.readFile(fileName, 'utf-8', function (err, data) {
        if (err) {
            console.error(err);
        } else {
            console.log(data);
            event.emit("readFinsh");
        }
    });
}


event.on("readFinsh", function () {
    console.log("文件读完了");
})

console.log('Read File:');

引用模块:

//getmodule.js
var mModule=require('./ReadFile');
mModule.ReadFile("taylor.txt")

运行getmodule.js就会引入读出文件内容并打印。上面这个例子有点类似于创建一个对象,但实际上和对象又有本质的区别,因为 require 不会重复加载模块,也就是说无论调用多少次 require,获得的模块都是同一个。

创建包

Node.js 的包类似于 C/C++ 的函数库或者 Java/.Net 的类库。Node.js 的包是一个目录,其中包含一个 JSON 格式的包说明文件 package.json。严格符 合 CommonJS 规范的包应该具备以下特征:

  • package.json 必须在包的顶层目录下;
  • 二进制文件应该在bin目录下;
  • JavaScript代码应该在lib 目录下;
  • 文档应该在doc目录下;
  • 单元测试应该在test目录下。
    这里有个要注意的就是如果没有package.json的话,node.js会尝试寻找 index.js 或 index.node 作为包的接口。如果都没有,就会报错

包管理器

Node.js包管理器,即npm是 Node.js 官方提供的包管理工具,它已经成了Node.js 包的 标准发布平台,用于 Node.js 包的发布、传播、依赖控制。npm 提供了命令行工具,使你可 以方便地下载、安装、升级、删除包,也可以让你作为开发者发布并维护包。

One thought on “Node.js笔记

发表评论

电子邮件地址不会被公开。 必填项已用*标注