原文地址在我的博客,转载请注明出处,谢谢!node模块是node的实现者,完成node的强大功能。node的核心模块包括events、fs、buffer、stream、cluster、http、net、一些操作系统和工具模块、全局对象等,本文将在对node的理解的基础上进一步探究node核心模块的具体细节核心功能。本文主要讨论的模块有:全局对象global及其重要属性、多进程集群、重要事件类EventEmitter、流Stream、文件系统fs、网络http,同时还介绍了节点框架express。概述本文首先介绍了全局对象global及其重要属性,以及多进程集群模块。文本节点全局对象global与浏览器对应的窗口相同。在node中,global是一个全局对象。任何定义在全局范围内的变量都会被保存为一个全局属性,称为全局变量。以下是global的一些重要属性:Module:module,require,exports这三个全局变量构成了node的模块定义和导入,是commonJS的实现。Node把每个文件看成一个模块,上面三个变量是在每个模块执行之前定义的,所以可以直接使用。让我们看看它们之间的协作://module1.jsexports.fun=function(a,b){returna+b;}//exports中绑定的属性可以被其他模块导入//module2.jsvarmodule1=require('./module1')module1.fun(3,2)//5相关机制:module代表了对这个模块的引用,所以module其实并不是全局的,而是每个模块局部的。除了导出,模块还有关于模块的其他属性。比如module.childrenexports其实就是module.exports的缩写,意思是这个模块的输出。需要注意的一点是exports={...}直接赋值给exports是不会输出的,因为exports已经提前定义好了,再次这样赋值会被覆盖,需要带上module:module.exports={...}require表示导入某个模块,只需要填写模块路径即可,在node_modules中填写模块名称即可,js文件不需要写扩展名。另外,由于V8引擎对ES6的不断支持,ES6的一些特性,比如promises和classes,也可以直接在node.js中使用。ES6模块也是node实验性引入的,稳定。详见nodejs中文网。您可以在node.green中查看支持的特性异步操作。setTimeout、setInterval、setImmediate、process.nextTicksetTimeout、setInterval与浏览器端相同。不同的是node实现了setImmediate(目前只有IE在浏览器端实现了该方法)。它表示在当前轮Node.js事件循环结束时要调用的函数。用于将一些需要长时间运行的操作放在一个回调函数中。节点主线程完成后面的其他语句后,会立即执行。回调函数,参数是一个函数,作为这个函数使用的参数,函数类似于setTimeout(fn,0),相当于在事件队列的尾部立即插入一个事件,但有区别。process.nextTick(fn,...args)表示当前调用栈结束后,在下一个事件执行前调用回调函数。Node提供了这个API来将复杂耗时的任务放在最后,让简单的任务先执行。让我们看看它们之间的比较:setTimeout(()=>console.log("setTimeout0"),0)setImmediate(()=>console.log("setImmediate"))process.nextTick(()=>console.log("nextTick"))//输出nextTicksetTimeout0setImmediateornextTicksetImmediatesetTimeout0不管process.nextTick写到哪里,总是第一个输出。不管setTimeout和setImmediate谁先来,都可能出现两个结果,其中setTimeout(fn,0)比setImmediate多一点。这是因为他们三个产生的事件被推送到不同的watchers(观察者)中——setTimeout被推送到timer观察者中,setImmediate是check观察者,process.nextTick()是idle观察者,而node中的顺序主线程在事件循环中调用watcher一般是idleobserver>checkobserver,idleobserver>timer观察者,check和timer不分先后,但是timer先于check的概率更高。节点进程:进程进程是节点对进程的表示,提供了操作进程的接口。流程可用于提供流程相关的信息和控制流程。进程提供的接口包括描述进程的一些状态(事件):exit、beforeExit、uncaughtException、Signal进程出口返回的状态码:UncaughtFatalException、SignalExits、Unused等进程相关信息:stdout、stderr、config、stdin、ExitCode、pid(进程号)等操作进程的方法:abort、chdir、cwd、kill(向进程发送信号)、exit、nextTick、getgid、setgid、uptime等:console,__filename,__dirname这些是全局变量,Node子进程可以在任何地方引用:child_process模块??一个进程只能使用一个CPU时间片。为了高效地利用多核CPU,node提供了一个child_process模块??,可以创建子进程(不是子线程)来帮助主进程高效地利用多核CPU来处理其他复杂的任务。我们之所以提供接口来创建子进程而不是子线程,是因为这样可以让我们拥有单一的程序状态,而不用担心状态同步、死锁、上下文切换开销等多线程编程中令人头疼的问题。这样一个进程就只有一个线程。虽然单线程也会带来一些问题,比如出错会导致整个应用程序退出等等,但是对此也有很好的解决方案。创建子进程Node有3个创建子进程的接口:exec/execFile:这两个都会创建子进程执行,执行结果存放在Buffer中。不同的是前者创建一个shell进程来执行命令,后者直接创建一个进程来执行可执行文件,所以前者适合执行shell命令然后获取输出,后者效率更高。这两个只适合输出轻量级的数据,因为输出结果存放在Buffer中。spawn:适用于进程输入输出数据比较大的情况,因为它支持以流的形式输入输出,可以用于任何命令。spawn的参数选项有一个stdio配置项,用于配置子进程和父进程之间的IO通道,还有一个detached配置子进程是否独立运行,可以创建常驻后台进程。总之,给子进程更多的灵活性。fork:fork实际上是spawn的一个特例。它将创建一个只能用于运行node.js程序的V8实例。与上面两种方式不同的是,fork会在父子进程之间建立一个IPC通道。您可以相互发送和接收消息——通过监听消息事件并调用发送方法,您可以在父进程和子进程之间进行通信。父子进程通信首先,三个API都返回ChildProcess实例,因此可以通过访问stdout属性获取输出。exec/execFile接口也可以在参数中绑定回调函数,获取子进程的stdout。const{exec,execFile,spawn,fork}=require("child_process")//exec/execFile接口既可以在参数中绑定回调函数获取输出流,也可以使用返回的ChildProcess实例constexec_process=exec(“节点child_process.js”,{},(err,stdout,stderr)=>{if(err){console.log(err)}elseif(stdout){console.log(stdout)}else{console.log(stderr)}})exec_process.stdout.on('data',(data)=>console.log(`${data}`))//spawn接口没有回调函数,只能使用返回的ChildProcessinstancetobindandmonitor数据函数获取子进程的输出log(`${data}`))//fork也可以使用返回的ChildProcess实例,注意配置项silent要设置为trueconstfork_process=fork('child_process.js',[],{'silent':true})fork_process.stdout.on('data',(data)=>console.log(`${data}`))其次,fork返回的ChildProcess实例有一个额外的内置通信通道IPC,它允许消息在父进程和子进程之间来回传递。//child_process.jsprocess.on('message',(data)=>{console.log(`messagefromParent:${data}`);})setTimeout(()=>{process.send('发送自child');},2000)//parent.jsconst{fork}=require("child_process")constp=fork('child_process.js',//要执行的脚本路径[],//传递的参数{})p.on('message',data=>{//监听子进程消息console.log(`messagefromchild:${data}`)})p.send('sendfromparent')//发送消息tochildprocesscluster:Cluster模块cluster模块是对child_process模块??的进一步封装,致力于解决单进程的NodeJSweb服务器无法充分利用多核CPU的问题。使用该模块可以简化多进程服务器程序的开发,让每个核心运行一个worker进程,通过主进程统一监听端口和分发请求。——七天学习node.jsconstcluster=require('cluster');consthttp=require('http');constnumCPUs=require('os').cpus().length;console.log(numCPUs)if(cluster.isMaster){console.log(`主进程${process.pid}正在运行`);//产生一个工作进程。for(leti=0;i
