Node 模块原理与用法详解

本文实例讲述了Node 模块原理与用法。分享给大家供大家参考,具体如下:

简介

V8引擎本身就是用于Chrome浏览器的JS解释部分,但是Ryan Dahl,把V8搬到服务器,用于做服务器的软件。
Node是一个专注于实现高性能Web服务器优化的专家,在遇到V8而诞生的项目

  • 没有历史包袱,没有同步I/O。不会出现一个同步I/O导致事件循环性能急剧降低的情况。
  • V8性能足够好,远远比Python,Ruby等其它脚本语言的引擎快。
  • JavaScript语言的闭包特性非常方便,比C中的回调函数好用。

Node可以让JavaScript运行在服务器端的平台开发,它让JavaScript的触角延伸到了服务器端,可以与PHP,JSP,Python,Ruby等语言实现后端开发。

但Node似乎有点不同:

  • Node不是一种独立的语言,与PHP,JSP,Python,Perl,Ruby的“即使语言,也是平台”不同,Node使用的是JavaScript进行编程,运行在JavaScript引擎上(V8)
  • 与PHP,JSP等相比(PHP,JSP,.net都需要运行在服务器程序上,Apache,Naginx,Tomcat,IIS),Node跳过了Apcahe,Naginx,IIS等HTTP服务器,它自己不用建设在任何服务器任何之上。Node的设计理念与经典架构(LAMP = Linux + Apache + MySQL + PHP) 有着很大的不同,可以提供强大的伸缩能力。
  • Node没有Web容器。
  • Node是花最小的硬件成本,追求更高的并发,更高的处理性能。

Node特点

所谓特点,就是Node如果解决服务器高性能瓶颈问题。
JavaScript有什么特点的时候,会立即想到 单线程事件驱动面向对象。但是JavaScript精髓 觉得是 this闭包作用域链函数。才使得这门语言魅力无穷。

单线程

在Java,PHP,或者.net 等服务器端语言中,会为每一个用户端连接创建一个新的线程。而每个线程需要耗费大约2MB内存。理论上,一个8GB内存的服务器可以同时连接的最大用户数4000个左右。要让Web应用程序支持更多的用户,就需要增加服务器的数量,而Web应用程序的硬件成本就上升了。
Node不为每个用户连接创建一个新的线程,而仅仅使用一个线程。当有用户连接了,就触发一个内部事件,并通过非阻塞I/O,事件驱动机制,让Node程序宏观上也是并行的。Node中,一个8GB内存的服务器,可以同时处理超过4万用户的连接。
单线程好处:操作系统完全不再有线程创建,销毁的时间开销。
单线程坏处:就是一个用户造成了线程的奔溃,整个服务都奔溃了,其它人的服务也就奔溃了。

单线程也能够造成宏观上的“并发”。

非阻塞I/O

非阻塞I/O non-blocking I/O

例子:访问数据库取得数据的时候,需要一段时间。
在传统的单线程处理机制中,在执行了访问数据库代码之后,整个线程都将暂停下来,等待数据库返回结果,才能执行后面的代码。也就是说I/O阻塞了代码的执行,极大降低了程序执行的效率

Node采用了非阻塞型I/O机制,因此在执行了访问数据库的代码之后,将立即转而执行后面的代码,把数据库返回的结果的处理代码放在回调函数中,从而提高了程序的执行效率。
当某个I/O执行完毕时,将以时间的形式通知执行I/O操作的线程,线程执行了这个事件的回调函数。为了处理异步I/O,线程必须有事件循环,不断的检查是否有未处理的时间。依次予以处理。
阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过多线程。而非阻塞模式下,一个线程永远在执行计算操作,这个线程的CPU核心利用率永远是100%。 有一种类似 : 与其多人工作,但是好多人闲着,倒不如一个人工作,往死里干活。

事件驱动
事件驱动 event-driven

在Node中,客户端请求建立连接,提交数据等行为,会触发相应的时间。在Node中,在一个ie时时刻,只能执行一个事件回调函数,但是在执行一个事件回调函数的中途,可以转而处理其它事件(比如:有新用户连接),然后返回继续执行原事件的回调函数。这种处理机制,称为:"事件环"机制。

Node底层是C++(V8也是C++) 编写。底层代码中,近半数都用户事件队列,回调函数队列的构建。用事件驱动来完成服务器的任务调度。用一个线程,担负起了处理非常多的任务。

单线程,减少内存开销,操作系统的内存换页。
如某一个任务,执行了,但是被I/O阻塞了,所以这个县城就阻塞了。非阻塞I/O,不会傻等I/O语句结束,而会执行后面的语句。利用事件驱动,不管是新用户的请求,还是老用户的I/O完成,都将以事件方式加入事件环中,等待调度。

Node所有的I/O都是异步的,回调函数嵌套回调函数。

Node是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。
Node的每个API都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发。
Node基本上所有的事件机制都是用设计模式中的观察者模式实现的。
Node单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数。

模块

moduel

Node中,以模块为单位划分所有功能,并且提供一个完整的模块加载机制,可以将应用程序话费为各个不同的部分。

Node中,一个JavaScript文件中定义的变量,函数,都只在这个文件内部有效果。

侠义的说,每一个JavaScript文件都是一个模块,而多个JavaScript文件之间可以相互require,共同实现一个功能,整体外对,又称之为广义上的模块

好处:

  • 减少重复代码量,增加可读性。
  • 方便进行代码规划。
  • 方面使用第三方模块。

当需要从JS文件外部引用到这些变量,函数时,必须使用exprots对象,或者module.exprots进行暴露。使用者需要使用require(); 函数引入这个JS文件。

function People( name,sex,age ){
  this.name = name;
  this.sex = sex;
  this.age = age;
}

People.prototype = {
  sayHello: function(){
    console.log(this.name+this.sex+this.age);
  }
};

// 暴露
module.exports = People;

// 使用
var People = require('./People.js');

var p1 = new People('zf','nv','23');

p1.sayHello();

一个JavaScript文件,可以向外exprots无数个变量,函数,对象,但是require(); 的时候,仅仅需要 载入一次JS文件即可。 所以,无形之后,会增加一个顶层命名空间。

// 变量
// 需要变量引用 使用
exports.a = 10;
// 直接需要变量值使用.
module.exports = name;

// 对象
module.exports = {
 name1: 123,
 name2: 456
}
// 暴露结果: { name1: 123, name2: 456 }

exports.msg = {
 name1: 1,
 name2: 2
}
// 暴露结果 : { msg: { name1: 1, name2: 2 } }

// 函数
exports.showMsg = function () {
}

// 暴露结果 : { showMsg: [Function] }
// 在 引用结果 需要 通过 变量 引用对象 执行
// var msg = require();
// msg.showMsg();

module.exports = function () {
}
// 暴露结果 [Function]
// 引入文件的 变量 直接执行

模板引擎

数据绑定,成为一个完整的HTML字符串。
Node中使用的模板:ejs 和 jade

后台模板引擎:

<ul>
  <% for(var i = 0 ; i < news.length ; i++){ %>
   <li><%= news[i] %></li>
  <% } %>
</ul>

// 模板中需要的数据
var dictionary = {
 a:6,
 news : ["xixi","haha"]
};

HTTP模块

主要类

Class: http.Server
var server = http.createServer();

server就是http.Server类的实例。

常用的方法有:

server.listen(port, [hostname], [backlog], [callback])
Class: http.ServerResponse
var server = http.createServer(function(req,res){ });

res就是 http.ServerResponse类的实例。

Class: http.IncomingMessage

``
var server = http.createServer(function(req,res){ });
``
req就是http.IncomingMessage类的实例。

server对象

可以使用on语法监听某个事件。

var http = require('http');
var server = http.createServer();

server.on('request',function ( req,res ) {
 res.setHeader('Content-type','text/html;charset=utf8');
 if ( req.url == '/' ){
  res.end('index');
 } else {
  res.end('404');
 }
});

server.listen(8080,'localhost');

req对象

每次上行请求头对象

req.headers //HTTP上行请求头

req.httpVersion // http请求的版本。现在基本上都是1.1
req.method  //  “GET”、”POST”就是请求的类型
req.url // 用户请求的网址

res对象

每次下行响应对象

res.end() // 每次都要有这个语句,表示这次的发送已经结束
  // 参数必须是string、buffer(图片、文件)。

res.write()  // 就是写HTTP下行请求的body

res.setHeader()     // 设置返回的报文头部

res.statusCode = 404;  // 设置状态码

res.writeHead()     // 和res.setHeader差不多
res.writeHead(288 , {"Content-Type":"text/plain"});

url模块

作用内置模块,解析url,解析地址。 分析和解析 URL 的工具

url.parse()

url.parse()就是用来解析网址,接收一个字符串,返回一个JSON:

var obj = url.parse("http://localhost:8080/a/b/c/1.html?name=ting&age=21"); 

url.parse方法第二个参数如果是true,那么返回的对象中的query就是json

query: { xingming: 'xiaoming', age: '12' }

querystring模块

querystring模块是专门用来解析GET请求的查询字符串的。

console.log( qs.parse('name=ting&age=21&hobby=run&hobby=sing') );
// 返回:{ name: 'ting', age: '21', hobby: [ 'run', 'sing' ] }

path模块

处理和转换文件路径的工具集,专门处理路径

path.basename()  返回路径中的文件名
path.dirname()  返回路径中的文件夹名
path.extname()  返回路径的拓展名

console.log( path.basename('/xixi/haha/a.html') ); //a.html
console.log( path.extname('/xixi/haha/a.html') ); //.html
console.log( path.dirname('/xixi/haha/a.html') ); ///xixi/haha

fs模块

文件处理模块,可以读文件,也可以写文件

fs.readFile();      //读取文件内容
fs.readDir();      //读取文件夹名
fs.appendFile();    //追加文件
fs.writeFile();     //写入文件(覆盖原有的)
fs.rename();      //修改文件名

自定义模块

每一个js文件中可以看成是一个小小的模块
require()谁,就会执行谁。就相当于调用一个函数。A require B, 先执行B全部语句,然后执行A的剩余语句。

require('./test/a.js'); 

每个js文件就是一个闭包,声明的函数、变量只在这个js文件内部有定义。
A require了 B , 那么B里面的所有路径都要按照A的路径写。

如果需要使用到其它文件中的变量,使用exports暴露出去。

exports.*** = ***;
testA .js
var a = 100;
exports.a = a;

主文件

var testA = requrie('./testA.js');
console.log( testA.a );

暴露唯一的接口,module.exports ,一般使用到构造函数。

如果只有写文件载入,会去默认文件夹下:node_modules 寻找是否有当前需要载入的文件

require('test.js'); 

也可以直接省略路径、省略文件名,只写文件夹名

require('aa'); 

实际上引用的是node_moduels文件夹里面的aa文件夹里面的index.js文件。
一般第三方模块,都放入node_modules文件夹中。

package.json

配置信息:

{
 "name": "my_package",  //项目名字
 "version": "1.0.0",  //版本号
 "main": "index.js",  //入口文件
 "keywords": [],    //关键词,就是搜索什么npm上能够显示你
 "author": "ag_dubs",  //作者
 "license": "ISC",   //版权协议
 "repository": {       //代码托管仓库,这个会自动生成一个连接
  "type": "git",
  "url": "https://github.com/ashleygwilliams/my_package.git"
 },
 "bugs": {        //如果发现bug应该交给谁
  "url": "https://github.com/ashleygwilliams/my_package/issues"
 },
  "dependencies": {
  "underscore": "*",
 "date-format" : "0.0.2"
 },
  "homepage": "https://github.com/ashleygwilliams/my_package"  //个人网站
} 

最重要的信息是:依赖

{
 "dependencies": {
  "underscore": "*",
 "date-format" : "^0.0.2"
 }
}

formidable

处理POST请求

// formidable 语法
var form = new formidable.IncomingForm();

// 设置上传路径
form.uploadDir = "./uploads";
form.parse(req, function(err, fields, files) {
 // fields是普通域,就是普通的文本框、单选按钮、复选按钮、textarea都存在这个对象里面
 // files是上传的文件信息
 var newname = df('yyyyMMddhhmmssSSS', new Date());

 fs.rename(files.touxiang.path , "./uploads/" + newname + ".jpg",function(err){
   if(err){
     res.end("error");
     return ;
   }
 });
 res.end("ok");
});

爬虫初级

需要的npm包:

  1. express
  2. request (后端发送请求的模块)
  3. cheerio (像前端一样操作拉取回来的数据)

爬虫以及Robots协议介绍:

  1. 爬虫,是中自动获取网页内容的程序。是搜索引擎的重要组成部分,因此搜索引擎优化很大程度上就是针对爬虫而做出的优化。
  2. robots.txt是一个文本文件,robots.txt是一个协议,不是一个命令。robots.txt是爬虫要查看的第一个文件。robots.txt文件告诉爬虫在服务器上什么文件是可以被查看的,搜索机器人就会按照该文件中的内容来确定访问的范围。

var express = require('express');
var app = express();
var cheerio = require('cheerio');

app.get('/', function(req, res){

  var request = require('request');

  request('https://linxingzhang.com', function(err, response, body) {
    if (!err && response.statusCode == 200) {
      $ = cheerio.load(body); // 和jquery的$('body') 一样

      res.json({
        panel: $('#link-panel li').length
      });
    }
  });

});

app.listen(3000);

使用supervisor启动

> supervisor start app.js

常用npm包

模块名 链接地址 简介
async async 异步操作管理
bl bl 二进制数据解析
bluebird bluebird 异步操作管理
browserify browserify 发布浏览器可用的包
bunyan bunyan 日志(logging)管理
chai chai 断言
chalk chalk 命令行彩色输出
co co 异步流程管理
colors colors 命令行彩色输出
commander commander 命令行工具
debug debug Debug输出器
dockerode dockerode Docker管理
duplexify duplexify Stream流操作工具
event-stream event-stream Stream流操作工具
express express Server服务器框架
hapi hapi Server服务器框架
koa koa Server服务器框架
glob glob 文件名匹配
grunt grunt 构建工具
gulp gulp 构建工具
hyperquest hyperquest 轻量级HTTP客户端
istanbul istanbul 测试用例覆盖率分析
JSONStream JSONStream Stream流管理工具
levelup levelup LevelDB
lodash lodash 函数式编程工具
log4js log4js 日志(logging)管理工具
minimatch minimatch 文件名匹配
minimist minimist 命令行操作
mocha mocha 单元测试
moment moment 日期时间输出
mongodb mongodb MongoDB
mysql mysql MySQL
nconf nconf 配置工具
needle needle 轻量级HTTP客户端
node-fetch node-fetch Fetch API
nodemailer nodemailer Email客户端
passport passport 登录和认证
pg pg Postgres
pump pump Stream流管理工具
redis redis Redis
request request HTTP客户端
restify restify REST API搭建
socket.io socket.io WebSocket实时通信
split2 split2 Stream流管理工具
tape tape 单元测试
through2 through2 Stream流管理工具
underscore underscore 函数式编程工具
ws ws Websockets
xml2js xml2js XML转换为JavaScript
http-server http-server 命令行的HTTP服务器
nrm nrm 更改NPM下载源
node-inspector node-inspector Node调试
supervisor supervisor 检测Node进程的服务
nodemon nodemon 在文件有变化之后会自动重启服务

希望本文所述对大家node.js程序设计有所帮助。

(0)

相关推荐

  • Nodejs进程管理模块forever详解

    接下来,就让我们看看forever能不能实现目标. 一.forever介绍 forever是一个简单的命令式nodejs的守护进程,能够启动,停止,重启App应用.forever完全基于命令行操作,在forever进程之下,创建node的子进程,通过monitor监控node子进程的运行情况,一旦文件更新,或者进程挂掉,forever会自动重启node服务器,确保应用正常运行. 二. forever安装 全局安装forever 复制代码 代码如下: ~ D:\workspace\javascri

  • Node.js模块加载详解

    JavaScript是世界上使用频率最高的编程语言之一,它是Web世界的通用语言,被所有浏览器所使用.JavaScript的诞生要追溯到Netscape那个时代,它的核心内容被仓促的开发出来,用以对抗Microsoft,参与当时白热化的浏览器大战.由于过早的发布,无可避免的造成了它的一些不太好的特性. 尽管它的开发时间很短,但是JavaScript依然具备了很多强大的特性,不过,每个脚本共享一个全局命名空间这个特性除外. 一旦Web页面加载了JavaScript代码,它就会被注入到全局命名空间,

  • Node.js中对通用模块的封装方法

    在Node.js中对模块载入和执行进行了包装,使得模块文件中的变量在一个闭包中,不会污染全局变量,和他人冲突. 前端模块通常是我们开发人员为了避免和他人冲突才把模块代码放置在一个闭包中. 如何封装Node.js和前端通用的模块,我们可以参考Underscore.js 实现,他就是一个Node.js和前端通用的功能函数模块,查看代码: 复制代码 代码如下: // Create a safe reference to the Underscore object for use below.  var

  • nodejs使用http模块发送get与post请求的方法示例

    本文实例讲述了nodejs使用http模块发送get与post请求的方法.分享给大家供大家参考,具体如下: GET请求 var http = require('http'); var querystring = require('querystring'); var data = { a: 123, time: new Date().getTime()};//这是需要提交的数据 var content = querystring.stringify(data); var options = {

  • Nodejs学习笔记之NET模块

    一,开篇分析 从今天开始,我们来深入具体的模块学习,这篇文章是这个系列文章的第三篇,前两篇主要是以理论为主,相信大家在前两篇的学习中, 对NodeJS也有一个基本的认识,没事!!!趁热打铁,让我们继续将NodeJS进行到底,好了废话不多说,直接进入今天的主题 "Net模块" ,那么"Net"应该如何理解那? 它是做什么用的那?(Net模块可用于创建Socket服务器或Socket客户端.NodeJS 的数据通信,最基础的两个模块是 Net 和 Http,前者是基于

  • Node.js中HTTP模块与事件模块详解

    Node.js的http服务器 通过使用HTTP模块的低级API,Node.js允许我们创建服务器和客户端.刚开始学node的时候,我们都会遇到如下代码: 复制代码 代码如下: var http = require('http'); http.createServer(function (req,res) {     res.end('Hello World\n'); }).listen(3000,"127.0.0.1"); console.log("Server funni

  • NodeJS的模块写法入门(实例代码)

    我们知道每个模块对应一个js文件,这篇写一个最简单的模块hello.js, 然后在另一个js文件(main.js)中require自定义的模块. hello.js 复制代码 代码如下: function hello(name) { console.log('hello, '+ name); } exports.hello = hello; main.js 复制代码 代码如下: var h = require('./hello'); h.hello('snandy'); 约定:hello.js和m

  • NodeJS学习笔记之(Url,QueryString,Path)模块

    一,开篇分析 这篇文章把这三个模块拿来一起说,原因是它们各自的篇幅都不是很长,其次是它们之间存在着依赖关系,所以依次介绍并且实例分析.废话不多说了,请看下面文档: (1),"Url模块" 来个小栗子: 复制代码 代码如下: var url = require('url');  var queryUrl = "http://localhost:8888/bb?name=bigbear&memo=helloworld" ;  console.log(typeof

  • nodejs文件操作模块FS(File System)常用函数简明总结

    件系统操作相关的函数挺多的.首先可以分为两大类. 一类是异步+回调的. 一类是同步的. 在这里只对异步的进行整理,同步的只需要在函数名称后面加上Sync即可 1. 首先是一类最常规的读写函数,函数名称和形式,应该是起源于C语言的. 复制代码 代码如下: fs.open(文件路径,读写标识,[文件mode值,666],回调函数(err,文件句柄fd));          fs.read(文件句柄fd,被写入的buffer,offset,length,position,回调函数(err, byte

  • NodeJS学习笔记之MongoDB模块

    一,开篇分析 这篇属于扩展知识篇,因为在下面的文章中会用到数据库操作,所以今天就来说说它(Mongodb模块). (1),简介 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bj

随机推荐