还记得之前说,NodeJs 拥有丰富的第三方模块吗?
如何利用现有的模块,快速、高效的实现需求呢?
第一部分 模块管理工具 几个关键字
1. nvm:主要管理nodejs版本; 2. npm:nodejs自带模块管理工具;
1. NPM 是什么?
npm 之于 Node.js ,就像 pip 之于 Python, gem 之于 Ruby, pear 之于 PHP 。
NPM 官网 给出解释如下:
npm 为你和你的团队打开了连接整个 JavaScript 天才世界的一扇大门。
它是世界上最大的软件注册表,每星期大约有 30 亿次的下载量,包含超过 600000 个 包(package) (即,代码模块)。
npm 由三个独立的部分组成:
网站:开发者查找包(package)、设置参数以及管理 npm 使用体验的主要途径;
注册表(registry):巨大的数据库,保存了每个包(package)的信息;
命令行工具 (CLI): 开发者通过 CLI 与 npm 打交道。
总之一句话,想简单高效的完成任务么?NPM 你值得拥有
接下来主要介绍使用
至于自我创建模块,暂不讨论
2. 安装配置 NodeJs 自带 npm, 故无需安装。 罗列几个常用的命令
# 查看 npm 命令列表 $ npm help # 查看各个命令的简单用法 $ npm -l # 查看 npm 的版本 $ npm -v # 查看 npm 的配置 $ npm config list -l $ npm list # 加上 global 参数,会列出全局安装的模块 $ npm list -global # 搜索模块 $ npm search <关键字> # 本地安装 $ npm install <package name> # 全局安装 $ sudo npm install -global <package name> $ sudo npm install -g <package name>
实例一 眼见为实 下载一个常用的框架—ExpressJs,借此展示一下效果,并熟悉一个 ExpressJs
$ mkdir first $ cd first $ npm install express $ node app.js Example app listening on port 3000!
实例二 初识 package.json 文件 简单说就是,记录文件,记录项目依赖的模块。
# 初始化一个package.json文件 $ npm init
实例说明
{ // 名称 "name": "npm", // 版本 "version": "1.0.0", // 描述 "description": "study npm", // 入口文件 "main": "app.js", // 模块依赖 "dependencies": { "express": "^4.16.4" }, "devDependencies": {}, // 执行脚本 "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, // 关键词 "keywords": [ "npm" ], // 作者 "author": "howard", // 协议 "license": "ISC" }
如我们需要下载ExpressJs,
# 一下命令即可将Express依赖加入到上边的文件中,偷个懒,不在重负写了 $ npm install express --save
实例三 更改npm源
可能你发现下载东西简直如龟速,这个你得感谢防火墙之父
为了更快更好的完成工作,我们可以用国内的淘宝 、清华等源;
淘宝镜像说明:这是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
使用方法类似,用cnpm即可
第二部分
Node.js 最大的特点就是异步式 I/O(或者非阻塞I/O)与事件紧密结合的编程模式。
1.阻塞I/O与非阻塞I/O概念 1.1 阻塞I/O(同步I/O) 线程在执行中如果遇到磁盘读写或网络通信(统称为I/O 操作 ), 通常要耗费较长的时间,这时操作系统会剥夺这个线程的 CPU 控制权,使其暂停执行,同时将资源让给其他的工作线程,这种线程调度方式称为阻塞 ,当I/O 操作 完成时,操作系统将这个线程的阻塞解除,恢复其对CPU的控制 ,令其继续运行。这种 I/O 模式就是通常的同步式 I/O(Synchronous I/O)或阻塞式 I/O (Blocking I/O)。
1.2 非阻塞I/O(异步I/O) 非阻塞I/O是针对所有的I/O不采用阻塞的策略 , 当线程遇到I/O 操作时, 不会阻塞等待完成 , 而是将I/O 操作发送给操作系统, 继续执行下一个语句 , 等操作系统完成I/O 操作以后, 会以事件的形式 发送通知执行I/O 操作的线程, 线程会在特定的时候处理这个事件; 也就是线程中会不停的监听时间循环, 看是否有未处理的事件, 并以此处理.
举个通俗的例子:例子来自知乎网友
你打电话问书店老板有没有《分布式系统》这本书,如果是`同步通信机制`,书店老板会说,你稍等,”我查一下", 然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。 而`异步通信机制`,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。 然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。
2.阻塞I/O与非阻塞I/O特点
同步I/O(阻塞式)
异步I/O(非阻塞式)
利用多线程提供吞吐量
单线程可实现高吞吐量
通过事件分割和线程调度利用多核CPU
通过功能划分利用多核CPU
需要由操作系统调度多线程使用多核CPU
可以将单进程绑定到单核 CPU
难以充分利用 CPU 资源
可以充分利用 CPU 资源
符合线性的编程思维
不符合传统编程思维
第二部分 异步式编程(函数式编程) 有异步I/O,就必然有异步编程。 首先以同步式编程的语法读取一个文件:
创建readfilesync.js, 并执行
var fs = require('fs'); var data = fs.readFileSync('/Users/51testing/Desktop/file.txt', 'utf-8'); console.log(data); console.log('end.');
打印的结果如下:
//执行 $ node /Users/51testing/Desktop/readfilesync.js 你好呀 end.
以上代码很容易理解, 自上而下的执行, 那么异步编程的做法呢?
创建readfileasync.js, 并执行
var fs = require('fs'); fs.readFile('/Users/51testing/Desktop/file.txt', 'utf-8', function(err, data) { if (err){ console.error(err); } else { console.log(data); } }); console.log('end.');
打印的结果如下:
//执行 $ node /Users/51testing/Desktop/readfileasync.js end. 你好呀 $
fs.readFile 调用时所做的工作只是将异步式 I/O 请求发给了操作系统
, 然后立即返回
并执行后面的语句,执行完以后进入事件循环监听事件。 fs 接到I/O 请求完成的事件时,事件循环会主动调用
回调函数以完成后续工作。因此我们会先看到 end.然后看到 file.txt 文件的内容。
2 NodeJs循环机制
Node.js 在什么时候会进入事件循环呢?
生命周期为: Node.js 程序由事件循环环开始,到事件循环结束
.
所有的逻辑都是事件的回调函数,所以 Node.js 始终在事件循环中,程序入口就是 事件循环第一个事件的回调函数。事件的回调函数在执行的过程中,可能会发出 I/O 请求或直接发射 (emit)事件,执行完成后再返回事件 循环,事件循环会会检查循环中有没有 处理的事件,直到到程序结束。
小技巧 Node 版本区别:
从对 ES6 的支持来简单的区分是
0.x 完全不支持ES6 4.x 部分支持ES6特性,并处在LTS阶段 5.x 部分支持ES6特性(比4.x多些),属于过渡产品,现在来说应该没有什么理由去用这个了 6.x 支持98%的ES6特性
参考链接
Node.js开发指南 深入浅出Node.js