Node.js 精华一页纸

    xiaoxiao2021-04-15  95

    Node.js 本质上是一个运行平台,提供提供文件/网络等系统资源,从而使js语言有了操纵服务端的能力。应该说Node.js的出现有 划时代的作用,以前只把js定位为前端语言,有了Node.js 后 js变成了全栈语言。

    除了Node.js以外,熟悉java的同志可以发现 java有相应的js执行引擎 rhino / nashron,通过java搭建平台后,可以达到Node.js 的功效。

    1、典型例子


    var http = require('http'); http.createServer(function (request, response) { // 发送 HTTP 头部 // HTTP 状态值: 200 : OK // 内容类型: text/plain response.writeHead(200, {'Content-Type': 'text/plain'}); // 发送响应数据 "Hello World" response.end('Hello World\n'); }).listen(8888);

    // 终端打印如下信息 console.log('Server running at http://127.0.0.1:8888/');

    步骤 I、引入XXX模块,这里 引入的是 Http模块 II、创建一个 node 的对象 III、通过node对象进行处理

    2、事件循环


    因为系统资源基本都是需要操作IO的,比如文件系统,网络等等。这就需要涉及IO操作的几种方式:同步 or 异步;阻塞 or 非阻塞 - 具体可以参照本博《java io 精华一页纸》 Node.js 因为是单进程单线程的,要处理这些IO,就只能采用异步的方式,即通过事件和回调函数来实现事件的处理

    这个非常类似 NIO 的并发机制,其实,执行 事件触发后的调用,如果不使用多线程或者队列,还是有阻塞的

    // I、引入 events 模块 var events = require('events'); // II、创建 eventEmitter 对象 var eventEmitter = new events.EventEmitter(); // III、创建事件处理程序 var connectHandler = function connected() { console.log('connect finish'); } // IV、绑定 connection 事件处理程序 eventEmitter.on('connection', connectHandler); // V、触发 connection 事件 eventEmitter.emit('connection'); console.log("exit");

    一般情况下,fs\net 这些模块都继承Events,很少直接使用 event 对象;

    特殊事件:error 类,系统发现 error类的事件,如果未定义处理方法,则node进程退出。

    3、组件化/模块化


    作为框架提供组件化/模块化几乎是一个标准配置;NodeJS 在模块方面,主要有两部分,一是 导出方法;另一个是导出对象 对象.js function ObjectExport(name){ this.name = name;

    this.showName = function(){ console.log(name); } }

    module.exports = ObjectExport

    这个时候就可以像系统自带对象一样引用这个对象 var obj = require("./useExport"); var aa = new obj("aa"); aa.showName();

    4、常见系统对象


    文件系统 fs -- 和java读写文件类似 打开文件 -- fs.open(path,flag,mode,callback); 读写文件 -- fs.read | fs.write 关闭文件 -- fs.close 其他删除,目录操作等等有很多

    fs.open('input.txt', 'r+', function(err, fd) { if (err) { return console.error(err); } console.log("success open file"); console.log("ready read file"); fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){ if (err){ console.log(err); }

    // 仅输出读取的字节 if(bytes > 0){ console.log(buf.slice(0, bytes).toString()); }

    // 关闭文件 fs.close(fd, function(err){ if (err){ console.log(err); } console.log("close success"); }); }); });

    网络操作 tcp/ip var net = require('net'); var server = net.createServer(function(connection) { console.log('client connected'); connection.on('end', function() { console.log('客户端关闭连接'); }); connection.write('Hello World!\r\n'); connection.pipe(connection); }); server.listen(3000, function() { console.log('server is listening'); });

    var net = require('net'); var client = net.connect(3000,'localhost', function() { console.log('连接到服务器!'); }); client.on('data', function(data) { console.log(data.toString()); client.end(); }); client.on('end', function() { console.log('断开与服务器的连接'); });

    操作系统 - os 可以获取操作系统信息

    dns

    域 - domain

    路径操作 - path

    ...

    5、IO流


    既然都是IO操作为主,一定需要处理系统流;JavaScript只有操作字符型的数据,没有二进制的数据,Node 提供了流处理类 I、Buffer类 a、定义buff (用法类似arraylist,指定容量|指定数组|字符串等) var buf = new Buffer("aaabbbcc","utf-8"); b、读写 buf.write("12345","utf-8"); buf.toString("utf-8",0,5) c、其他操作 转换json buf.toJSON(buf); 类似集合操作 比较 compare | 合并 concat | 截取 slice

    II、Stream流 Stream 是一个抽象接口(类似于Java的 InputStream 这种),Node.js中很多涉及IO操作的都实现了该接口,比如 http请求的 request 四种流类型 Readable - 可读 类似InputStream | Writable - 可写 类似OutputStream | Duplex - 可读可写 类似RandomAccessFile | Transform - 写入数据然后读 流常见的事件有 data - 数据就绪 | end - 流结束 | error - 读取流错误 | finish - 所有数据已写入

    a、基本流

    var fs = require("fs"); var data = ''; var readerStream = fs.createReadStream('streamfile.js'); readerStream.setEncoding('UTF8'); readerStream.on('data', function(chunk) { data += chunk; });

    readerStream.on('end',function(){ console.log(data); });

    readerStream.on('error', function(err){ console.log(err.stack); });

    var writeStream = fs.createWriteStream("out.txt"); writeStream.write(data); writeStream.end(); writeStream.on('finish', function(){ console.log("Write Finish"); });

    console.log("Process Exit");

    b、管道 -- 类似于 Java的pipe readerStream.pipe(writerStream) -- 只需要把读流和写流联系在一起即可。

    可以把 管道不断链接起来,实现链式 流操作

    var fs = require("fs"); var zlib = require('zlib');

    // 读取 streamlink.js ,然后压缩,最后再写入新的压缩文件 fs.createReadStream('streamlink.js') .pipe(zlib.createGzip()) .pipe(fs.createWriteStream('streamlink.js.gz'));

    console.log("finish");

    6、多进程


    nodejs 是单进程 单线程 (用户处理是单线程,但nodejs 肯定有一个事件线程在轮询) 模式运行,通过事件驱动来处理并发;这在某些场合下并不能满足,所以NodeJS提供了多进程的用法。

    创建子进程的三种方式(每个子进程都携带 child.stdin child.stdout child.stderr 三个流) -- 这个做法和H5的多线程理念非常类似

    exec -- 类似 Java 的 Rumtime.exec, 启动一个子进程执行命令 spawn -- 使用命令行参数创建新的进程 fork -- 类似于 C 的fork 一个子进程出来

    const fs = require('fs'); const child_process = require('child_process');

    for(var i=0; i<3; i++) { var workerProcess = child_process.exec('node support.js '+i, function (error, stdout, stderr) { if (error) { console.log(error.stack); console.log('Error code: '+error.code); console.log('Signal received: '+error.signal); } console.log('stdout: ' + stdout); console.log('stderr: ' + stderr); });

    workerProcess.on('exit', function (code) { console.log('子进程已退出,退出码 '+code); }); }

    7、其他知识


    REPL 交互式解释器 -- 命令终端下执行nodejs代码 系统自带全局对象和属性 -- 这点和浏览器对象差不多,常见的 console / process, __filename / setTimeout 工具库 util -- 提供了大量的公共方法 NPM -- 包管理工具 Express -- Web框架 ...

    转载请注明原文地址: https://ju.6miu.com/read-670808.html

    最新回复(0)