Node js 探讨之 初识node
2015-12-12 16:43
507 查看
前言:工作之余,在周末利用闲暇的时间探讨下node.js技术,充实自己的硬实力,扩充视野!
参考来源:http://www.runoob.com/nodejs/nodejs-http-server.html
说明:主要目的是记录自己的成长之路.多年以后再回首时能会想起当初的奋斗之路!
一 创建第一个应用
仍然是参考教程,这里整理了下步骤:(window版)
1.去node.js的官网下载 window版的Node,js http://nodejs.cn/
2.安装完毕后
(1)打开window cmd命令行,输入 node --version(能正常输出版本号)
(2)打开node.exe,输入 console.log('Hello!');(能正常输出)
3.在硬盘其它地方,创建一个测试项目文件夹,里面创建testServer.js,内容如下:
参考来源:http://www.runoob.com/nodejs/nodejs-http-server.html
说明:主要目的是记录自己的成长之路.多年以后再回首时能会想起当初的奋斗之路!
一 创建第一个应用
仍然是参考教程,这里整理了下步骤:(window版)
1.去node.js的官网下载 window版的Node,js http://nodejs.cn/
2.安装完毕后
(1)打开window cmd命令行,输入 node --version(能正常输出版本号)
(2)打开node.exe,输入 console.log('Hello!');(能正常输出)
3.在硬盘其它地方,创建一个测试项目文件夹,里面创建testServer.js,内容如下:
var http = require('http'); http.createServer(function(request,response){ //发送 HTTP头部 //Http状态值 200代表ok //内容类型,头部是 text,文本类型 response.writeHead(200,{'Content-Type':'text/plain'}); //发送响应数据 response.end('Hello Word\n'); }).listen(8888); //终端打印信息,node.js是单线程的,所以执行listen成功之后才执行这个输出 console.log('Server running at http://127.0.0.1:8888');[/code]4.打开cmd命令行(注意,这里不是node.exe-因为node.exe是node的交互解释器)
然后进入创建的项目目录,(我这里为:D:\programing\NodeJS\project\test001),
然后运行 (node testServer.js)
最终控制台正常输出打印信息
5.打开浏览器,输入(http://127.0.0.1:8888/)-服务监听的端口以及地址
可以正常显示打印信息
至此,第一个Node.js 应用就已经创建并运行完毕!
二 NPM使用
由于现在的node.js安装时已经集成NPM,所以并不需要像以前一样那么复杂的安装了.
1.只需要 在cmd中输入(npm -v)就可以看到当前的npm版本了.
2.npm常见命令:NPM提供了很多命令,例如install和publish,使用npm help可查看所有命令。 使用npm help <command>可查看某条命令的详细帮助,例如npm help install。 在package.json所在目录下使用npm install . -g可先在本地安装当前命令行程序,可用于发布前的本地测试。 使用npm update <package>可以把当前目录下node_modules子目录里边的对应模块更新至最新版本。 使用npm update <package> -g可以把全局安装的对应命令行程序更新至最新版。 使用npm cache clear可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人。 使用npm unpublish <package>@<version>可以撤销发布自己发布过的某个版本代码。
3.在命令行中通过npm下载express模块
注意: 将安装包放在 ./node_modules 下(运行 npm
命令时所在的目录),如果没有 node_modules 目录,会在当前执行 npm 命令的目录下生成 node_modules 目录
比如:在 D:programing\NodeJS\project\test001 中运行 npm install express 就是将express模块安装到这个文件夹中
4.安装完毕express模块后(其实也顺带安装了一些其它模块),可以通过 npm ls 查看已安装的模块
注意:目前采用的是本地安装(因为可以被requires引用)
三 Node.js REPL(交互解释器-Read-Eval-Print-Loop)
说明:类似于windows的cmd终端和linux的shell终端,Node.js也有自己的终端,可以识别用户的输入,并执行任务.
1.直接在node.js的安装目录打开node.exe即可打开终端
2.在cmd中 输入 node 也可进入node的终端
3.连续按 两次 ctrl+c 即可退出终端
4.在终端中可以写自己的逻辑代码,并且能在控制台输出
5.一些常用命令ctrl + c - 退出当前终端。 ctrl + c 按下两次 - 退出 Node REPL。 ctrl + d - 退出 Node REPL. 向上/向下 键 - 查看输入的历史命令 tab 键 - 列出当前命令 .help - 列出使用命令 .break - 退出多行表达式 .clear - 退出多行表达式 .save filename - 保存当前的 Node REPL 会话到指定文件 .load filename - 载入当前 Node REPL 会话的文件内容。
具体参考:http://www.runoob.com/nodejs/nodejs-repl.html
四 Node.js 的处理机制
node.js是单线程(这个单线程是指开发过程中开发人员使用的是单线程,而底层的实现仍然是多线程-将耗时的操作代理给了操作系统或多线程)
1.通过回调方法来处理异步事件.下面是异步模型大致过程(地址:http://segmentfault.com/q/1010000000190024)其实现在的异步模型大同小异,大致过程如下(分三层): (1).(最重要的)维护一个事件反应堆,用epoll或者select或者kqueue来做,反应堆的作用就是用同步的方式处理异步问题,在反应堆上注册好事件后如果相应的事件发生,就调用其回调函数,一般情况下反应堆是一个进程内全局唯一的。 <pre name="code" class="javascript">(2)<span style="font-family: Arial, Helvetica, sans-serif;">.上层的buffer,维护一系列的buffer用于管理每一个连接的数据,可以把buffer看做是一个对象。一般在一个连接到达的时候分配一个buffer对象,然后上层的连接注册事件的时候是注册到buffer上,buffer再注册到反应堆中。</span>(3)<span style="font-family: Arial, Helvetica, sans-serif;">.就是一个个的连接对象,把每一个来自外部的连接都抽象为一个具体的对象,用于管理每一个连接,其中这个对象就包含了上面所说的buffer对象和其他一些状态。</span>处理并发的过程就是这样的:(1)<span style="font-family: Arial, Helvetica, sans-serif;">.为监听套接口在反应堆注册一个事件,此事件发生调用对应的回调,一般情况是accept这个连接,然后为这个连接创建连接对象,统一管理。</span>(2)<span style="font-family: Arial, Helvetica, sans-serif;">.为此连接创建buffer对象,并注册对应的读写错误事件的回调(上层对于buffer的读写事件回调都是业务层来控制的了).</span>(3)<span style="font-family: Arial, Helvetica, sans-serif;">.(所谓的排队机制也不是完全正确)在加入监听队列后是离散的,准确来说epoll中是由一颗红黑树维护的,每一个事件的先后顺序跟它达到的顺序有关。</span>(4)<span style="font-family: Arial, Helvetica, sans-serif;">.维护了众多的连接对象,也就是这里的并发情况了,如果有事件发生会调用回调来处理,理论上无阻塞情况减少了很多CPU的wait,这部分时间用于处理真正的业务,所以异步模型能够带来很高的CPU处理能力,减少等待,单位时间处理的事件越多,从外部来看并发就很高,实际上也是一个串行的工作状态,但是串行过程没有等待。</span>
2.node.js中使用事件驱动模型,核心是(events.EventEmitter-一些重要的API的实现都是继承自这个得,比如fs,http)
五 Node.js Buffer(缓冲区)
js本身只有字符串数据类型,没有二进制数据类型
但是在处理像Tcp流或文件流时,必须使用到二进制数据.因此,在node.js中,定义了一个buffer类,该类用来创建一个专门存放二进制数据的缓存区.
(在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存
-来源:http://www.runoob.com/nodejs/nodejs-buffer.html)
六 Node.js Stream(流)Stream 是一个抽象接口,Node 中有很多对象实现了这个接口。例如,对http 服务器发起请求的request 对象就是一个 Stream,还有stdout(标准输出)。Node.js,Stream 有四种流类型: Readable - 可读操作。 Writable - 可写操作。 Duplex - 可读可写操作. Transform - 操作被写入数据,然后读出结果。 所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有: data - 当有数据可读时触发。 end - 没有更多的数据可读时触发。 error - 在接收和写入过程中发生错误时触发。 finish - 所有数据已被写入到底层系统时触发。
通过操作流,可以轻易实现各种文件之间的转换,压缩等操作
七 Node.js模块系统
为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。
模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C++ 扩展(http://www.runoob.com/nodejs/nodejs-module-system.html)
1.Node.js 中通过 require(模块名)引入相应模块
2.各个模块(原生模块和本地模块)之间的引入优先级如图
3.require获取对应模块后,只会获取该模块的exports对象,所以需要把提供给外部调用的方法写入exports对象中(如exports.test=***)
4.也可以通过(module.exports = 对象)来指定本模块的特定导出对象
八 Node.js路由
示例:
1.router.js/* * @description自定义路由构造函数 */ function RouteCustom(){ }; /* * @description扩展原型 */ RouteCustom.prototype.route =function(pathName){ console.log("About to route a request for "+pathName); }; //将导出模块指定为路由 module.exports = new RouteCustom();2.server.js//引入http模块 var http = require("http"); //引入url模块 var url = require("url"); /* * @description 自定义服务器构造函数 */ function Server(){ console.log("create a new server"); }; /* * @description扩展原型 */ Server.prototype.start =function(route){ function onRequest(request, response) { var pathname = url.parse(request.url).pathname; console.log("Request for " + pathname + " received."); if(route&&typeof(route)=='function'){ 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."); }; //将导出模块指定为自定义服务器 module.exports = new Server();
3.main.jsvar server = require("./server.js"); var router = require("./router.js"); server.start(router.route);4.cmd进入项目文件夹 然后执行(node main.js)
就已经开启了服务了,绑定了8888端口,然后接受到网络请求时,就会打印出来
代表路由里面已经接收到了服务器传过去的参数,现在测试版只是默认传入path,
也可以换位 请求参数,其它的.
(相当于每一次服务器的请求都会转交有效消息给路由)
相关文章推荐
- node.js的安装以及grunt的使用
- [Linked List]Reverse Nodes in k-Group
- LeetCode Swap Nodes in Pairs
- [Linked List]Swap Nodes in Pairs
- [Linked List]Delete Node in a Linked List
- nodejs基础
- Node.js的优点和缺点(转载)
- nodejs 配置及其nodejs管理工具npm
- nodejs初探(四)实现一个多人聊天室
- nodejs初探(三)实现一个简单的socket交互
- nodejs初探(二)第一个nodejs程序“hello world”
- nodejs初探(一)环境搭建,开发工具安装
- LeetCode 237 Delete Node in a Linked List
- [Linked List]Remove Nth Node From End of List
- node.js express开发web问题
- 10、osg::AnimationPath,osg::NodeVisitor类
- LeetCode 237:Delete Node in a Linked List
- leetcode Remove Nth Node From End of List
- node 学习笔记 - Modules 模块加载系统 (1)
- [转]为什么我要用 Node.js? 案例逐一介绍