node.js
node.js是建立在谷歌Chrome的JavaScript引擎(v8)的web应用程序框架。
node.js 自带的运行环境可在JavaScript脚本的基础上解释和执行。这个运行是运行在浏览器以外的任何机器上执行JavaScript代码。所以也可以在服务端运行,Node.js还提供了各种丰富的JavaScript模块库,它极大简化了使用Node.js来扩展Web应用程序的研究与开发。
特性
Node.js库的异步和事件驱动的API全部都是异步就是非阻塞。它主要是指基于Node.js的服务器不会等待API返回的数据。服务器移动到下一个API调用,Node.js发生的事件通知机制后有助于服务器获得从之前的API调用的响应。
非常快的内置谷歌Chrome的V8 JavaScript引擎,Node.js库代码执行是非常快的。
单线程但高度可扩展 - Node.js使用具有循环事件单线程模型。
没有缓冲 - Node.js的应用从来不使用缓冲任何数据。这些应用只是输出数据在块中。
应用场景
适合:I/O 绑定应用程序,数据流应用,数据密集型实时应用(DIRT),JSON API的应用程序,单页面应用。
不适合:CPU密集型应用。
下载安装完成后,通过cmd启动执行文件。
node.js - Hello World
node -v 查看当前node版本。
通过编写js文件,然后再cmd当前目录运行文件。
1 var http = require('http'); 2 http.createServer(function(req,res){ 3 res.writeHead(200,{'Content-Type':'text/plain'}); 4 res.end('Hello World '); 5 }).listen(1337,'127.0.0.1'); 6 console.log('Server running at http://127.0.0.1:1337/');
执行当前文件目录执行node hello.js
起一个简单的服务,在浏览器可输入地址,后显示
node.js - npm
npm 表示节点程序包管理器。是Node.js包/模块的在线软件仓库;可以在命令行实用程序安装包,作为Node.js版本管理和依赖包管理。
npm -v 查看当前npm版本。(一般安装node.js自带npm)-g 表示资源包全局安装。
npm install express (一个实用的web框架)
npm ls 查询
package.json
package.json是存在于任何Node应用程序/模块的根目录,并用于定义一个包的属性。
Node.js - 回调
回调是一种异步相当于一个函数。回调函数被调用在完成既定任务。Node大量使用了回调。Node所有的API写的都是支持回调的这样一种方式。例如,一个函数读取一个文件可能开始读取文件,并立即返回控制到执行环境 使得下一个指令可以马上被执行。一旦文件 I/O 完成,它会调用回调函数,同时传递回调函数,该文件作为参数的内容。因此不会有堵塞或等待文件I/O。这使得Node.js高度可扩展,因此可以处理大量的请求,而无需等待任何函数来返回结果。
阻塞代码/非阻塞代码。
1 var fs = require('fs'); 2 3 fs.readFile('text.txt',function(err,data){ 4 if(err) return console.log(err); 5 console.log(data.toString()); 6 }) 7 console.log("end!!");
事件循环 && 事件驱动编程
Node JS是单线程应用程序,但它通过事件和回调的概念,支持并发。NodeJS的每一个API都是异步的,作为一个单独的线程,它使用异步函数调用来维护并发。Node使用观察者模式。Node线程保持一个事件循环,每当任何任务完成后得到结果,它触发通知事件侦听函数来执行相应的事件。
Node.js使用大量事件,这也是为什么Node.js相对于其他类似技术比较快的原因之一。当Node启动其服务器,就可以简单地初始化其变量,声明函数,然后等待事件的发生。
1 // 声明需要事件 2 var events = require('events'); 3 // 创建事件对象 4 var eventEmitter = new events.EventEmitter(); 5 // 声明触发事件执行的函数 6 var connected = function connected() { 7 console.log('connection succesful!') 8 eventEmitter.emit('data_received.'); 9 } 10 // 绑定事件 11 eventEmitter.on("connection",connected); 12 eventEmitter.on("data_received",function(){ 13 console.log('data received succesfully.'); 14 }); 15 // 事件触发 16 eventEmitter.emit('connection'); 17 console.log('code end!');
错误处理:
1 var fs = require("fs"); 2 3 fs.readFile('test.txt', function (err, data) { 4 if (err){ 5 console.log(err.stack); 6 return; 7 } 8 console.log(data.toString()); 9 }); 10 console.log("Program Ended");
事件监听的添加移除与触发
1 // 需要事件 2 var events = require('events'); 3 // 创建事件对象 4 var eventEmitter = new events.EventEmitter(); 5 // 事件1 6 var listner1 = function listner1() { 7 console.log('this is 11111'); 8 } 9 // 事件2 10 var listner2 = function listner2() { 11 console.log('this is 22222'); 12 } 13 // 事件监听addListener与on效果相同 14 eventEmitter.addListener('connection',listner1); 15 eventEmitter.on('connection',listner2); 16 // 另一种写法 17 var eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection'); 18 console.log(eventListeners + " Listner(s) listening to connection event"); 19 // 触发事件 20 eventEmitter.emit('connection'); 21 // 移除事件监听 22 eventEmitter.removeListener('connection', listner1); 23 console.log("Listner111 will not listen now. removeListener"); 24 // 再触发事件 25 eventEmitter.emit('connection'); 26 // 添加事件监听 27 eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection'); 28 console.log(eventListeners + " Listner(s) listening to connection event"); 29 30 console.log("Program Ended.");
Buffer 类 缓冲器
Buffer类是一个全局类,可以在应用程序,无需导入缓冲模块进行访问。缓冲区是一种整数数组并对应于原始存储器V8堆以外分配。 缓冲区不能调整大小。
在 ECMAScript 2015
引入 TypedArray
之前,JavaScript 语言没有读取或操作二进制数据流的机制。 Buffer
类被引入作为 Node.js API 的一部分,使其可以在 TCP 流或文件系统操作等场景中处理二进制数据流。
TypedArray
现已被添加进 ES6 中,Buffer
类以一种更优化、更适合 Node.js 用例的方式实现了 Uint8Array
API。
1 var buffer = new Buffer(26); 2 console.log("buffer length: " + buffer.length); 3 var data = "YiiBai.com"; 4 5 buffer.write(data); 6 console.log(data + ": " + data.length + " characters, " + Buffer.byteLength(data, 'utf8') + " bytes"); 7 8 var buffer1 = buffer.slice(0,14); 9 console.log("buffer1 length: " + buffer1.length); 10 console.log("buffer1 content: " + buffer1.toString()); 11 12 for (var i = 0 ; i < 26 ; i++) { 13 buffer[i] = i + 97; // 97 is ASCII a 14 } 15 console.log("buffer content: " + buffer.toString('ascii')); 16 17 var buffer2 = new Buffer(4); 18 19 buffer2[0] = 0x3; 20 buffer2[1] = 0x4; 21 buffer2[2] = 0x23; 22 buffer2[3] = 0x42; 23 24 //reading from buffer 25 console.log(buffer2.readUInt16BE(0)); 26 console.log(buffer2.readUInt16LE(0)); 27 console.log(buffer2.readUInt16BE(1)); 28 console.log(buffer2.readUInt16LE(1)); 29 console.log(buffer2.readUInt16BE(2)); 30 console.log(buffer2.readUInt16LE(2)); 31 32 var buffer3 = new Buffer(4); 33 buffer3.writeUInt16BE(0xdead, 0); 34 buffer3.writeUInt16BE(0xbeef, 2); 35 console.log(buffer3); 36 37 buffer3.writeUInt16LE(0xdead, 0); 38 buffer3.writeUInt16LE(0xbeef, 2); 39 40 console.log(buffer3); 41 42 //convert to a JSON Object 43 var json = buffer3.toJSON(); 44 console.log("JSON Representation : "); 45 console.log(json); 46 47 //Get a buffer from JSON Object 48 var buffer6 = new Buffer(json); 49 console.log(buffer6); 50 51 //copy a buffer 52 var buffer4 = new Buffer(26); 53 buffer.copy(buffer4); 54 console.log("buffer4 content: " + buffer4.toString()); 55 56 //concatenate a buffer 57 var buffer5 = Buffer.concat([buffer,buffer4]); 58 console.log("buffer5 content: " + buffer5.toString());
node.js 数据流
数据流是从源数据读取或写入数据到目标对象以。在节点中,有四种类型的流:
-
Readable - 数据流,其是用于读操作
-
Writable - 数据流,用在写操作
-
Duplex - 数据流,其可以用于读取和写入操作
-
Transform - 双相类型流,输出基于输入进行计算
每种类型的流是EventEmitter,并且一次引发几个事件。例如,一些常用的事件是:
-
data - 当有数据可读取时触发此事件
-
end - 当没有更多的数据读取时触发此事件
-
error - 当有错误或接收数据写入时触发此事件
-
finish - 当所有数据已刷新到底层系统时触发此事件
1 var fs = require("fs"); 2 var data = ''; 3 //create a readable stream 4 var readerStream = fs.createReadStream('text.txt'); 5 6 //set the encoding to be utf8. 7 readerStream.setEncoding('UTF8'); 8 9 //handle stream events 10 readerStream.on('data', function(chunk) { 11 data += chunk; 12 }); 13 14 readerStream.on('end',function(){ 15 console.log(data); 16 }); 17 18 readerStream.on('error', function(err){ 19 console.log(err.stack); 20 }); 21 console.log("-------------Program Ended---------------");
1 var fs = require("fs"); 2 var data = 'Yiibai.Com'; 3 //create a writable stream 4 var writerStream = fs.createWriteStream('text1.txt'); 5 6 //write the data to stream 7 //set the encoding to be utf8. 8 writerStream.write(data,'UTF8'); 9 10 //mark the end of file 11 writerStream.end(); 12 13 //handle stream events 14 writerStream.on('finish', function() { 15 console.log("Write completed."); 16 }); 17 18 writerStream.on('error', function(err){ 19 console.log(err.stack); 20 }); 21 console.log("--------------Program Ended---------------");
node.js 文件系统
--同步&异步
每一个fs模块的方法都有同步和异步形式。异步方法接受一个最后的参数为完成回调函数,而回调函数的第一个参数是错误。它优选使用异步方法来代替同步方法,前者从未阻塞程序执行,而后者则会阻塞。
1 var fs = require("fs"); 2 var buffer = new Buffer(1024); 3 4 //Example: Opening File打开文件 5 function openFile(){ 6 console.log(" Open file--------"); 7 fs.open('test.txt', 'r+', function(err,fd) { 8 if (err) console.log(err.stack); 9 console.log("File opened"); 10 }); 11 } 12 13 //Example: Getting File Info 统计信息 14 function getStats(){ 15 console.log(" Getting File Info---------"); 16 fs.stat('test.txt', function (err, stats) { 17 if (err) console.log(err.stack); 18 console.log(stats); 19 console.log("isFile ? "+stats.isFile()); 20 console.log("isDirectory ? "+stats.isDirectory()); 21 }); 22 } 23 24 //Example: Writing File 写 25 function writeFile(){ 26 console.log(" Write file-----------"); 27 fs.open('test2.txt', 'w+', function(err,fd) { 28 var data = "Yiibai.com - Simply Easy Learning!"; 29 buffer.write(data); 30 31 fs.write(fd, buffer,0,data.length,0,function(err, bytes){ 32 if (err) console.log(err.stack); 33 console.log(bytes + " written!"); 34 }); 35 }); 36 } 37 38 //Example: Read File 读取 39 function readFile(){ 40 console.log(" Read file----------"); 41 fs.open('test1.txt', 'r+', function(err,fd) { 42 if (err) console.log(err.stack); 43 fs.read(fd, buffer,0,buffer.length,0,function(err, bytes){ 44 if (err) console.log(err.stack); 45 console.log(bytes + " read!"); 46 if(bytes > 0){ 47 console.log(buffer.slice(0,bytes).toString()); 48 } 49 }); 50 }); 51 } 52 // 关闭 53 function closeFile(){ 54 console.log(" Close file-------------"); 55 fs.open('test.txt', 'r+', function(err,fd) { 56 if (err) console.log(err.stack); 57 fs.close(fd,function(){ 58 if (err) console.log(err.stack); 59 console.log("File closed!"); 60 }); 61 }); 62 } 63 // 删除 64 function deleteFile(){ 65 console.log(" Delete file-----------"); 66 fs.open('test1.txt', 'r+', function(err,fd) { 67 fs.unlink('test1.txt', function(err) { 68 if (err) console.log(err.stack); 69 console.log("File deleted!"); 70 }); 71 }); 72 } 73 // 缩短,删节? 74 function truncateFile(){ 75 console.log(" Truncate file------------"); 76 fs.open('test.txt', 'r+', function(err,fd) { 77 fs.ftruncate(fd, function(err) { 78 if (err) console.log(err.stack); 79 console.log("File truncated!"); 80 }); 81 }); 82 } 83 84 function createDirectory(){ 85 console.log(" Create Directory--------------"); 86 fs.mkdir('test',function(err){ 87 if(!err){ 88 console.log("Directory created!"); 89 } 90 if(err && err.code === 'EEXIST'){ 91 console.log("Directory exists!"); 92 } else if (err) { 93 console.log(err.stack); 94 } 95 }); 96 } 97 // 移除 98 function removeDirectory(){ 99 console.log(" Remove Directory---------------"); 100 fs.rmdir('test',function(err){ 101 if(!err){ 102 console.log("Directory removed!"); 103 } 104 if (err) { 105 console.log("Directory do not exist!"); 106 } 107 }); 108 } 109 // 监听 110 function watchFile(){ 111 fs.watch('test.txt', function (event, filename) { 112 console.log('event is: ' + event); 113 }); 114 } 115 116 //Opening file 117 openFile(); 118 119 //Writing File 120 writeFile(); 121 122 //Reading File 123 readFile(); 124 125 //Closing Files 126 closeFile(); 127 128 //Getting file information 129 getStats(); 130 131 //Deleting Files 132 deleteFile(); 133 134 //Truncating Files 135 truncateFile(); 136 137 //Creating Directories 138 createDirectory(); 139 140 //Removing Directories 141 removeDirectory(); 142 143 //Watching File Changes 144 watchFile();
node.js - 进程 (process)
process 是一个全局性对象,并用于表示Node进程。
Process(进程)是一个eventEmitter,并且它发出下列事件
Process(进程)提供了许多有用的特性,以更好地控制系统的相互作用。
Process(进程)提供了许多有用的方法,以更好的控制系统的相互作用。
1 var util = require('util'); 2 3 //printing to console 4 process.stdout.write("Hello World!" + " "); 5 6 //reading passed parameter 7 process.argv.forEach(function(val, index, array) { 8 console.log(index + ': ' + val); 9 }); 10 11 //executable path 12 console.log(process.execPath); 13 14 //print the current directory 15 console.log('Current directory: ' + process.cwd()); 16 17 //print the process version 18 console.log('Current version: ' + process.version); 19 20 //print the memory usage 21 console.log(util.inspect(process.memoryUsage()));
node.js - psth
path 模块用于处理和转换文件路径。path模块可以使用以下语法导入。
var path = require("path")
1 var path = require("path"); 2 3 //normalization 4 console.log('normalization : ' + path.normalize('/test/test1//2slashes/1slash/tab/..')); 5 6 //join 7 console.log('joint path : ' + path.join('/test', 'test1', '2slashes/1slash', 'tab', '..')); 8 9 //resolve 10 console.log('resolve : ' + path.resolve('test.js')); 11 12 //extName 13 console.log('ext name : ' + path.extname('test.js'));
node.js - Net
net 模块是用来创建服务器和客户端。它提供了一个异步网络包装。 net模块可以使用以下语法导入。
var net = require("net")
node.js - DNS
dns 模块是用来做实际的DNS查找,以及使用底层操作系统的名称解析功能..它提供了一个异步网络包装。dns模块可以使用以下语法导入。
var dns = require("dns")
node.js - Domain
domain 模块是用于拦截未处理的错误。这些未处理的错误可以使用内部绑定或外部绑定来拦截。如果错误都那么不处理,那么Node应用会崩溃。
-
内部绑定 - 错误发生执行代码是在一个域的run方法。
-
外部绑定 - 使用它的add方法将错误发生明确地加入到域。
domain(域)模块可以使用以下语法导入。
var domain = require("domain")
域模块的Domain类是用来提供路由错误以及未捕获异常活动域对象的功能。 这是一个EventEmitter的子类。为了处理它捕获错误,监听它的错误事件。它使用如下的语法创建:
var domain = require("domain"); var domain1 = domain.create();
一点基础内容,没深入研究,了解基础,创建文本服务应用,以后再进行跟深层次的挖掘!!