NodeJS基础和常用API

问题1:process.exit事件

[javascript]  view plain  copy
  1. process.on('exit'function(code)  {  
  2.   // 这里必须只能是同步代码快,而不能是异步的  
  3.   setTimeout(function() {  
  4.     console.log('This will not run');  
  5.   }, 0);  
  6.   console.log('About to exit with code:', code);  
  7. });  
(1)code如果是0表示成功退出,如果是非0那么表示非正常退出。具体 参见node.js官网
(2)process对象是一个全局变量,可以在任何时候进行访问,他是一个EventEmitter的实例

(3)当进程准备退出的时候触发。在这时候没有任何方法能够阻止事件循环的退出,当所有的exit事件处理程序执行完毕之后就会退出。因此,在这时候你必须执行一些同步的请求,而不能是异步的。因此最好检查一下模块此时的状态,如通过unit检测。回调函数只有一个参数,也就是当前进程正在退出的程序代码块
问题2:beforeExit事件
   当Node.js清空了他的事件循环,并且没有任何逻辑去处理的时候会触发。通常node.js当没有任何工作进程的时候会退出,但是beforeExit可以产生异步的调用,从而让node.js继续执行
   beforeExit在以下情况下不会调用如process.exit或者触发了未捕获的异常的时候。这个事件不能作为exit的替代方案,除非是为了继续执行后续的程序
问题3:uncaught exception事件

[javascript]  view plain  copy
  1. process.on('uncaughtException'function(err){  
  2.   console.log(`Caught exception: ${err}`);  
  3. });  
  4. setTimeout(function() {  
  5.   console.log('This will still run.');  
  6. }, 500)  
  7. // Intentionally cause an exception, but don't catch it.  
  8. nonexistentFunc();//异常被捕获,然后退出  
  9. console.log('This will not run.');  

(1)默认情况下,node.js处理这种异常的方式是通过把消息栈打印到错误流中,然后退出。通过添加这个事件可以替换这种默认的行为
(2)uncaughtException是一种粗糙的异常处理手段,一般情况下最好不要用。
(3)在事件处理中抛出的异常不会被捕获到,这时候程序会抛出一个非0的数字,同时会打印输出流。这是为了防止循环调用的产生

问题4:unhandledRejection事件

[javascript]  view plain  copy
  1. process.on('unhandledRejection'function(reason, p) {  
  2.     console.log("Unhandled Rejection at: Promise ", p, " reason: ", reason);  
  3.     // application specific logging, throwing an error, or other logic here  
  4. });  
  5. var Q = require('q');  
  6. //获取defer  
  7.  var deferred = Q.defer();  
  8.   deferred.reject('你没有权限');  

 结果打印:Unhandled Rejection at: Promise  { state: 'rejected', reason: '你没有权限' }  reason:你没有权限

(1)unhandledRejection当promise对象被拒绝,同时没有设置异常处理的回调函数时候触发。这个事件可以跟踪那些Promise被拒绝了,同时还没有设置异常处理函数。
(2)第一个参数是reason,也就是拒绝的原因,通常是一个Error对象,p代表被拒绝的Promise对象

问题5:SIGN Event事件

[javascript]  view plain  copy
  1. process.stdin.resume();  
  2. // Start reading from stdin so we don't exit.  
  3. //从标准输入流中读取数据,不让程序退出  
  4. process.on('SIGINT'function() {  
  5.   console.log('Got SIGINT.  Press Control-D to exit.');  
  6. });  

(1)这是事件当接收到SIGN事件的时候会触发,通常是通过Ctrl+c来触发,其它内容参见官方API

问题6:process.arch获取处理器架构

[javascript]  view plain  copy
  1. console.log('This processor architecture is ' + process.arch);  
问题7:process.argv获取控制台传入的参数

[javascript]  view plain  copy
  1. // print process.argv  
  2. process.argv.forEach(function(val, index, array) {  
  3.   console.log(`${index}: ${val}`);  
  4. });  
如果控制台打印:node argv.js qinliang sex=male 21

结果为:

[javascript]  view plain  copy
  1. 0: C:\Program Files\nodejs\node.exe  
  2. 1: C:\Users\Administrator\Desktop\nodeJS\process\argv.js  
  3. 2: qinliang  
  4. 3: sex=male  
  5. 4: 21  
问题8:通过process.chdir更改目录,通过process.cwd获取当前目录

[javascript]  view plain  copy
  1. console.log(`Starting directory: ${process.cwd()}`);  
  2. //${process.cwd()}获取当前的目录  
  3. try {  
  4.   process.chdir('/tmp');  
  5.   console.log(`New directory: ${process.cwd()}`);  
  6. }  
  7. catch (err) {  
  8.   console.log(`chdir: ${err}`);  
  9. }  
问题9:process.config获取当前node.js执行的一些配置

[javascript]  view plain  copy
  1. console.log(process.config);  
问题10:process.connected

[javascript]  view plain  copy
  1. console.log(process.connected);//如果connected设置为false那么不能发送任何信息,当process.disconnect被调用的时候其值就是false  
问题11:process.disconnect()

      关闭到父进程的IPC通道,如果没有任何进程保持子进程的存活,那么可以让子进程关闭。如果node.js没有IPC通道,那么这时候process.disconnect()将会是undefined

问题12:process.env

[javascript]  view plain  copy
  1. console.log(process.env);  

(1) 返回用户的环境,包括系统所有的信息,甚至连我系统的tomcat都打印出来了

(2)你可以修改这个对象,但是这个属性不会反映到当前的进程外面去,也就是下面的代码不会其作用

[javascript]  view plain  copy
  1. node -e 'process.env.foo = "bar"' && echo $foo  
 但是下面这种修改会反映到进程外:(注意process.env添加的变量全部会转化为string)

[javascript]  view plain  copy
  1. process.env.name= 'qinlaing';  
  2. console.log(process.env.name);//打印'qinliang'  
通过delete可以删除process.env上的变量

[javascript]  view plain  copy
  1. process.env.TEST = 1;  
  2. delete process.env.TEST;  
  3. console.log(process.env.TEST);  
问题13:process.execArgv

与 process.argv 类似,不过是用于保存 node特殊(node-specific) 的命令行选项(参数)。这些特殊的选项不会出现在 process.argv 中,而且 process.execArgv 不会保存 process.argv 中保存的参数(如 0:node 1:文件名 2.3.4.参数 等), 所有文件名之后的参数都会被忽视。这些选项可以用于派生与与父进程相同执行环境的子进程。

Git bash中输入:node --harmony execArgv.js --version

在execArgv.js中输入:

[javascript]  view plain  copy
  1. console.log(process.execArgv);//这时候打印['--harmony']  
问题14:process.execPath

[javascript]  view plain  copy
  1. C:\Program Files\nodejs\node.exe//获取开启当前进程的程序的绝对路径  
问题15:process.exit([code])

  退出当前进程,如果没有设置code,那么code默认为0表示成功退出

问题16:process.exitCode

  如果进程正常退出,或者调用process.exit没有指定参数那么其值为0,否则就是非0。如果有process.exit传入了code,那么任何前面通过process.exitCode设置的值都是无效

     也可以参考中文API,之所以写这篇博客还是为了好好认识一些这个process模块!

问题17:process.hrtime

[javascript]  view plain  copy
  1. var time = process.hrtime();  
  2. // [ 1800216, 25 ]  
  3. setTimeout(function(){  
  4.   var diff = process.hrtime(time);  
  5.   // [ 1, 552 ]  
  6.  //diff[0]表示的是秒,而第二个diff[1]表示的是纳秒!  
  7.   console.log('benchmark took %d nanoseconds', diff[0] * 1e9 + diff[1]);  
  8.   // benchmark took 1000000527 nanoseconds  
  9. }, 1000);  

(1)返回当前进程的高分辨时间,形式为 [seconds, nanoseconds]数组。它是相对于过去的任意时间。该值与日期无关,因此不受时钟漂移的影响。主要用途是可以通过精确的时间间隔,来衡量程序的性能。你可以将之前的结果传递给当前的 process.hrtime() ,会返回两者间的时间差,用来基准和测量时间间隔。

(2)diff[0]表示的是秒,第二个参数表示的纳秒

[javascript]  view plain  copy
  1. process.on('SIGHUP'function() {  
  2.   console.log('Got SIGHUP signal.');  
  3. });  
  4. setTimeout(function(){  
  5.   console.log('Exiting.');  
  6.   process.exit(0);  
  7. }, 100);  
  8. console.log('window中的pid为:'+process.pid);  
  9. //打印5664  
  10. process.kill(process.pid, 'SIGHUP');  
  11. //windows下会抛出错误Error: kill ENOSYS  

(1)发送信号给进程. pid 是进程id,并且 signal 是发送的信号的字符串描述。信号名是字符串,比如 'SIGINT' 或 'SIGHUP'。
如果忽略,信号会是 'SIGTERM'。如果进程没有退出,会抛出错误。信号 0 可以用来测试进程是否存在。
(2)注意,虽然这个这个函数名叫process.kill,它仅是信号发射器,就像kill 系统调用。信号发射可以做其他事情,不仅是杀死目标进程。
(3)windows将会抛出错误,如果这个process.pid用于杀死进程组.

(4)如果目标进程不存在,将会抛出错误。特殊情况下可以发送一个0去检测进程是否存在!

问题18:process.mainModule

[javascript]  view plain  copy
  1. console.log(process.mainModule);  
process.mainModule将会返回如下的信息

[javascript]  view plain  copy
  1. Module {  
  2.   id: '.',  
  3.   exports: {},  
  4.   parent: null,  
  5.   filename: 'C:\\Users\\Administrator\\Desktop\\nodeJS\\process\\mainModule.js',  
  6.   loaded: false,  
  7.   children: [],  
  8.   paths:  
  9.    [ 'C:\\Users\\Administrator\\Desktop\\nodeJS\\process\\node_modules',  
  10.      'C:\\Users\\Administrator\\Desktop\\nodeJS\\node_modules',  
  11.      'C:\\Users\\Administrator\\Desktop\\node_modules',  
  12.      'C:\\Users\\Administrator\\node_modules',  
  13.      'C:\\Users\\node_modules',  
  14.      'C:\\node_modules' ] }  

(1)该方法是require.main 的备选方法。不同点,如果主模块在运行时改变,require.main可能会继续返回老的模块。可以认为,这两者引用了同一个模块。和 require.main 一样, 如果没有入口脚本,将会返回undefined 。

问题19:process.memoryUsage方法

(1)返回node.js进程内存的使用情况,单位为bytes。rss(resident set size)表示进程的常驻内存部分,进程的内存总共分为几个部分,一部分是rss,其余在交换区或者文件系统中。

(2)heapTotal和heapUsed描述内存的使用情况。两者都反映的是V8堆内存的信息,heapTotal是堆中总共申请的内存的存量,heapUsed表示堆内存中使用的内存量。

[javascript]  view plain  copy
  1. { rss: 14716928, heapTotal: 6981296, heapUsed: 2944724 }  
问题20:process.nextTick(callback[, arg][, ...])

[javascript]  view plain  copy
  1. console.log('start');  
  2. process.nextTick(function() {  
  3.   console.log('nextTick callback');  
  4. });  
  5. console.log('scheduled');  

打印如下结果:

[javascript]  view plain  copy
  1. start  
  2. scheduled  
  3. nextTick callback  

(1)一旦当前事件循环结束,调用回调函数。这不是 setTimeout(fn, 0) 的简单别名,这个效率更高。它在任何额外的I/O事件之前触发,包括定时器。

(2)当前事件循环结束那么就会触发回调函数。每次调用nextTick只是将回调函数放入队列中,当下一轮Tick时取出执行,定时器采用红黑树的事件复杂度为O(lg(n))而nextTick时间复杂度为O(1)

在对象构造后,在 I/O 事件发生前,你又想改变附加事件处理函数时,这个非常有用。

[javascript]  view plain  copy
  1. function MyThing(options) {  
  2.   this.setupOptions(options);  
  3.   //把下一个函数的执行放入队列中  
  4.   process.nextTick(function() {  
  5.     this.startDoingStuff();  
  6.   });  
  7. }  
  8. var thing = new MyThing();  
  9. thing.getReadyForStuff();  
  10. // thing.startDoingStuff() gets called now, not before.  
要保证你的函数一定是 100% 同步执行,或者 100% 异步执行
[javascript]  view plain  copy
  1. function definitelyAsync(arg, cb) {  
  2.   if (arg) {  
  3.     process.nextTick(cb);  
  4.     return;  
  5.   }  
  6.   fs.stat('file', cb);  
  7. }  
注意:nextTick 队列会在完全执行完毕之后才调用 I/O 操作。因此,递归设置 nextTick 的回调就像一个 while(true); 循环一样,将会阻止任何 I/O 操作的发生。
问题21:进程的pid和node.js运行的平台

[javascript]  view plain  copy
  1. console.log(`This process is pid ${process.pid}`);  
  2. //进程的pid值  
  3. console.log(`This platform is ${process.platform}`);  
  4. //进程指定的平台'darwin', 'freebsd', 'linux', 'sunos' or 'win32'  
问题22:process.release

[javascript]  view plain  copy
  1. { name: 'node'//node.js下是node  
  2.   sourceUrl: 'https://nodejs.org/download/release/v5.7.1/node-v5.7.1.tar.gz',//taz.gz文件包含当前的release  
  3.   headersUrl: 'https://nodejs.org/download/release/v5.7.1/node-v5.7.1-headers.ta  
  4. r.gz',  
  5.   libUrl: 'https://nodejs.org/download/release/v5.7.1/win-x86/node.lib' }  
问题22:process.send(message[, sendHandle[, options]][, callback])
(1)如果node.js具有IPC通道,那么可以用该方法发送消息到他的父进程。在父进程的ChildProcess对象上将会接受一个message事件
(2)这个方法将会调用JSON.Stringify来序列化message对象
(3)如果node.js没有IPC通道,那么process.send()将会是undefined
问题23:process.stderr

process.stderr 和 process.stdout 和 node 里的其他流不同,他们不会被关闭(end() 将会被抛出),它们不会触发 finish 事件,并且写是阻塞的。
问题24:process.stdin

[javascript]  view plain  copy
  1. process.stdin.setEncoding('utf8');  
  2. //设置输入的流的编码  
  3. process.stdin.on('readable'function(){  
  4.     //为process.stdin注册事件readable  
  5.   var chunk = process.stdin.read();  
  6.   if (chunk !== null) {  
  7.     process.stdout.write(`data: ${chunk}`);  
  8.   }  
  9. });  
  10. //为process.stdin注册end事件  
  11. process.stdin.on('end'function()  {  
  12.   process.stdout.write('end');  
  13. });  

(1)process.stdin 可以工作在老模式里,和 v0.10 之前版本的 node 代码兼容。
(2)在老的流模式里,stdin流默认暂停,必须调用 process.stdin.resume() 读取。可以调用 process.stdin.resume() 切换到老的模式。
如果开始一个新的工程,最好选择新的流,而不是用老的流。

问题25:process.umask([mask])

[javascript]  view plain  copy
  1. var newmask = 0o022;  
  2. //如果为process.unmask指定了参数那么返回值就是oldmask,也就是原来的掩码  
  3. var oldmask = process.umask(newmask);  
  4. console.log(  
  5.   `Changed umask from ${oldmask.toString(8)} to ${newmask.toString(8)}`  
  6. );  

设置或读取进程文件的掩码。子进程从父进程继承掩码。如果mask 参数有效,返回旧的掩码。否则,返回当前掩码

问题26:process.version,process.versions等

[javascript]  view plain  copy
  1. console.log(process.uptime());  
  2. //node.js已经运行的时间  
  3. console.log(process.version);  
  4. //内置的属性,反映node版本号,如v5.7.1  
  5. console.log(process.versions);  
  6. //内置的版本号和依赖  
process.versions还可以打印node.js的依赖

[javascript]  view plain  copy
  1. { http_parser: '2.6.2',  
  2.   node: '5.7.1',  
  3.   v8: '4.6.85.31',  
  4.   uv: '1.8.0',  
  5.   zlib: '1.2.8',  
  6.   ares: '1.10.1-DEV',  
  7.   icu: '56.1',  
  8.   modules: '47',  
  9.   openssl: '1.0.2g' }  

很多内容可以继续阅读极客学院的API

下面是FileSystem模块相关知识:

问题1:fs.watch方法的使用

[javascript]  view plain  copy
  1. var fs=require('fs');  
  2. //获取文件加载模块,用于监听当前目录的文件的变化  
  3. fs.watch('./'function(event, filename){  
  4.   console.log(`event is: ${event}`);  
  5.   if (filename) {  
  6.     console.log(`filename provided: ${filename}`);  
  7.   } else {  
  8.     console.log('filename not provided,  please check');  
  9.   }  
  10. });  
(1)API签名:fs.watch(filename[, options][, listener])
(2)第一个参数可以是文件名也可以是一个目录,返回的对象是fs.FSWatcher
(3)第二个参数是一个对象,其中包括recursive和persistent布尔值。其中persistent表示进程是否应该继续(当文件被监听的时候),recursive表示子文件夹是否也应该被监听。默认是:{ persistent: true, recursive: false }。第三个函数有两个参数为event和filename,其中event之可能是rename/change,filename表示触发这个事件的文件名!
(4)不要期待这个API在所有的平台上有一致的表现
问题2:fs.watchFile(filename[, options], listener)

[javascript]  view plain  copy
  1. var fs=require('fs');  
  2. fs.watchFile('readMe'function(curr, prev) {  
  3.   console.log(`the current mtime is: ${curr.mtime}`);  
  4.   console.log(`the previous mtime was: ${prev.mtime}`);  
  5. });  

(1)persistent参数和watch函数是一样的,但是option还是可以指定一个interval参数,表示每隔多久对这个文件进行轮询,查看其是否修改了
(2)回调函数有两个参数,第一个是当前的对象,第二个是上一个对象,他们都是fs.Stat对象
(3)这个方法相对于watch来说有以下特点:他是通过轮询的方式监听文件是否改变,同时他可以兼容不同的平台
(4)watch事件比watchFile和unwatchFile更加高效。建议用watch替换其它两者

(5)每次存取文件的时候都会触发watchFile,但是只有修改了文件才会触发watch!

问题3:fs.access(path[, mode], callback)

[javascript]  view plain  copy
  1. var fs=require('fs');  
  2. fs.access('./file.js', fs.R_OK | fs.W_OK, function(err) {  
  3.   console.log(err ? 'no access!' : 'can read/write');  
  4. });  

(1)检测用户对于一个文件的存取权限,mode是一个可选的整数,表示存取的权限。取值可能如下:
   fs.F_OK:文件对于当前进程是可见的,用于判断一个文件是否存在,但是对于rwx权限没有任何反应。这是默认的模式
   fs.R_OK:文件对于当前进程是可见的,用于判断一个文件是否存在,但是对于rwx权限没有任何反应。这是默认的模式
   fs.W_OK:文件对于当前进程可写
   fs.X_OK:文件可以执行,在window上相当于fs.F_OK
(2)回调函数表示只要有一个权限没有就报错,并把error给函数的参数

关于文件存取权限的内容可以参看:linux umask命令-预设文件权限掩码

问题4:fs.createWriteStream(path[, options])

[javascript]  view plain  copy
  1. var fs=require('fs');  
  2. //读取流  
  3. fs.createReadStream('sample.txt', {start: 90, end: 99});  

下面是一个默认的options对象:

[javascript]  view plain  copy
  1. {  
  2.   flags: 'w',  
  3.   defaultEncoding: 'utf8',  
  4.   fd: null,  
  5.   mode: 0o666,  
  6.   autoClose: true  
  7. }  

(1)返回值是一个新的ReadStream对象,而且和highWaterMark不同的是,相同的参数下,这个方法的默认返回的流大小是64Kb,而不是16kb
(2)options中可以传入一个end和start用于读取一部分的数据而不是所有的数据,而且start和end也包含在读取的数据之中。encoding参数可以Buffer接受的任何编码
(3)如果指定了fd,那么ReadStream会忽略path,就是默认只用这个文件描述符。这时候没有任何open方法触发,同时fd是阻塞的,非阻塞的文件描述符应该传递给net.Socket
(4)如果指定了autoClose为false,那么文件描述符不会自动关闭,即使抛出了异常。因此你应该手动关闭它,确保没有文件描述符泄漏。如果设置为true,在onerror或者onend中文件描述符会自动关闭
(5)mode指定了文件的模式(权限或者粘接位),但是只有文件被创建的时候
(6)如果options是string,那么就是指定编码

问题5:fs.appendFile(file, data[, options], callback)

[javascript]  view plain  copy
  1. var fs=require('fs');  
  2. fs.appendFile('./test','data to append',function(err){  
  3.     if(err)throw err;  
  4.     console.log('data appended!');  
  5. })  

(1)第三个参数是options,其中encoding指定编码,mode指定文件的读写方式默认是0o666,flag默认是'a'表示append
(2)如果文件不存在那么就创建,data可以是Buffer或者string
(3)如果option是string那么就是指定encoding。file可以是文件名或者文件描述符
(4)任何指定的文件描述符都会被打开,然后追加数据(指定的文件描述符不会被自动关闭)

问题6:fs.stat(path, callback)

其中callback中第二个参数就是fs.Stats对象,该对象有以下属性:

[javascript]  view plain  copy
  1. { dev: 1219237462,  
  2.   mode: 33206,  
  3.   nlink: 1,  
  4.   uid: 0,  
  5.   gid: 0,  
  6.   rdev: 0,  
  7.   blksize: undefined,//总之,除了文件名以外的所有文件信息,都存在inode之中  
  8.   ino: 562949954098169,//文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为"索引节点"。  
  9.   size: 188,//文件大小的字节数  
  10.   blocks: undefined,  
  11.   atime: Sat Mar 19 2016 10:20:15 GMT+0800 (中国标准时间),//存取文件,如cat操作  
  12.   mtime: Thu Mar 24 2016 15:58:26 GMT+0800 (中国标准时间),//修改内容  
  13.   ctime: Thu Mar 24 2016 15:58:26 GMT+0800 (中国标准时间),//修改内容会改变,但是修改权限等也会改变,总之只要inode数据变化了就都会变化。如rename,read(2),write(2)  
  14.   birthtime: Sat Mar 19 2016 10:20:15 GMT+0800 (中国标准时间) //文件创建时间  
  15. }  

属性说明如下表:

数字下标
关联键名(自 PHP 4.0.6)
说明
0
dev
设备名
1
ino
号码
2
mode
inode 保护模式
3
nlink
被连接数目
4
uid
所有者的用户 id
5
gid
所有者的组 id
6
rdev
设备类型,如果是 inode 设备的话
7
size
文件大小的字节数
8
atime
上次访问时间(Unix 时间戳)
9
mtime
上次修改时间(Unix 时间戳)
10
ctime
上次改变时间(Unix 时间戳)
11
blksize
文件系统 IO 的块大小
12
blocks
所占据块的数目

用法如下:

[javascript]  view plain  copy
  1. var fs=require('fs');  
  2. fs.stat('./file.js',function(err,stats){  
  3.     //其中stats是一个 fs.Stats对象  
  4.     console.log(stats);  
  5. })  

(1)其中stats是一个fs.Stats参数,参见官网。其中atime(access time)表示最近存取文件的时间;mtime表示最近一次修改文件数据的时间;ctime表示最近一次修改文件状态的时间;birthtime表示创建文件的时间。关于文件的属性可以参考Linux的inode的理解 atime、mtime、ctime IO系统性能之一:衡量性能的几个指标 UNIX内核(11):FS系统调用——link()和unlink()

问题7:fs.chmod(path, mode, callback)

[javascript]  view plain  copy
  1. var fs=require('fs');  
  2. fs.chmod('./file.js',33206,function(err){  
  3.    //我们现在获取文件的读取模式  
  4.    fs.stat('./file.js',function(err,stats){  
  5.        console.log(stats.mode);  
  6.    })  
  7. })    
(1)用于修改文件的访问模式,操作完成后的回调只接收一个参数,可能会出现异常信息。

问题7:fs.chown(path, uid, gid, callback)

[javascript]  view plain  copy
  1. var fs=require('fs');  
  2. //chown就是change owner的缩写把,改变文件的所有权,第二个参数是user id  
  3. fs.chown('file.js', 1, 2, function(err){  
  4.  if(err){  
  5.   console.log(err);  
  6.  }else{  
  7.   console.log("change done");  
  8.  }  
  9. })  

(1)path目录路径;uid 用户ID;gid群体身份 (指共享资源系统使用者的身份);callback回调 ,传递异常参数 err。而且uid和gid都是整数值

问题8:fs.fchown(fd, uid, gid, callback)

[javascript]  view plain  copy
  1. var fs=require('fs');  
  2. //通过文件描述符来更改文件所有权,第二个参数是'a'表示是追加  
  3. fs.open('file.js''a'function (err, fd) {   
  4.      if (err) {   
  5.       throw err;   
  6.      }   
  7.      //通过文件描述符来修改  
  8.  fs.fchown(fd, 1, 2, function(err){   
  9.       if (err) {   
  10.        throw err;   
  11.       }   
  12.     console.log('fchmod complete');   
  13.     //这时候必须手动关闭文件描述符  
  14.       fs.close(fd, function () {   
  15.        console.log('Done');   
  16.       });   
  17.  })   
  18. });  
(1)用于使用文件描述符来修改文件的所有权,但是必须注意,必须手动关闭文件描述符
(2)这里的fchown第一个参数是error对象

下面是HTTP模块的相关知识理解:

第一部分:Class: http.ServerResponse对象的一些方法

问题1:response.addTrailers方法

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     //最大连接数是10,超过拒绝!  
  4.     server.MaxConnections=10;  
  5.     //获取连接数  
  6.      console.log(server.connections);  
  7.     res.writeHead(200,{'Content-Type':'text/plain','Trailer':'Content-MD5'});  
  8.     res.write('I am the data from server');  
  9.     res.addTrailers({'Content-MD5':'7895bf4b8828b55ceaf47747b4bca667'});  
  10.         //调用end方法  
  11.     res.end('我是qinl');  
  12. }).listen(8888,'localhost');  
通过这个方法添加的头部是在回应数据的消息头后面的。只有在使用了chunked encoding的时候才会在响应中发送,如果是HTTP1.0那么就会被丢掉 。如果你打算发送trailler消息那么必须发送Trailer头!

问题2:response.end([data][, encoding][, callback])
 这个方法告诉服务器,所有的响应头和响应体已经发送;服务器可以认为消息结束。response.end() 方法必须在每个响应中调用。 如果指定了data那么相当于同时调用了response.write(data, encoding)和response.end(callback);如果指定了callback那么会在响应流结束后调用回调

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     res.writeHead(200,{'Content-Type':'text/plain'});  
  4.     res.end('我是高山上的鱼','utf8',function(){  
  5.         console.log('所有数据发送成功');  
  6.     });  
  7. }).listen(8888,'localhost');  
问题3:response.finished的值

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     res.writeHead(200,{'Content-Type':'text/plain'});  
  4.     console.log(res.finished);  
  5.     //在end之前为false  
  6.     res.end('我是高山上的鱼','utf8',function(){  
  7.         console.log('所有数据发送成功');  
  8.     });  
  9.     console.log(res.finished);  
  10.     //在end之后就是true  
  11. }).listen(8888,'localhost');  
注意:在end调用之前为false,之后为true
问题4:response.getHeader

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.        res.setHeader('Name','MoutainFish');  
  4.     var header=res.getHeader('Name');  
  5.       res.writeHead(200);  
  6.         console.log(header);  
  7.     //显示调用end方法  
  8.       res.end();  
  9. }).listen(8888,'localhost');  
读取一个在队列中但是还没有被发送至客户端的header。名字是大小写不敏感。仅能在头部被flushed前调用。
问题5:response.headsSent

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.        res.setHeader('Name','MoutainFish');  
  4.     var header=res.getHeader('Name');  
  5.         console.log(res.headersSent);  
  6.         //打印false  
  7.       res.writeHead(200);  
  8.     console.log(res.headersSent);  
  9.      //打印true  
  10.     //显示调用end方法  
  11.       res.end();  
  12. }).listen(8888,'localhost');  
注意:在writeHead之前是false,之后是true
问题6:response.removeHeader

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.      //移除要被发送到客户端的http头  
  4.       res.removeHeader('date');  
  5.       res.end();  
  6. }).listen(8888,'localhost');  
注意:这时候就不会发送date头给浏览器
问题7:response.sendDate

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.      //移除要被发送到客户端的http头  
  4.      res.sendDate=false;  
  5.       res.end();  
  6. }).listen(8888,'localhost');  
注意:默认服务器会发送Date头。我们不建议取消这个头的发送,仅仅在测试的时候建议取消,HTTP需要响应中的Date头!
问题8:response.setHeader

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     //如果需要发送多个http同名头那么应该用数组否则会发生覆盖!  
  4.     res.setHeader('Set-Cookie', ['name=qinliang''sex=male']);  
  5.     res.setHeader('name','qinliang');  
  6.     res.writeHead(200,{'name':'fkl'});  
  7.     //这时候的name是fkl而不是qinliang  
  8.       res.end();  
  9. }).listen(8888,'localhost');  

注意:setHeader中的头会和writeHead中的头合并,而且后者的优先级比前者高!
问题9:response.setTimeout

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     var date=+new Date(),date1;  
  4.     while(true){  
  5.         date1=Date.now();  
  6.       if(date1-date>3000){  
  7.         break;  
  8.       }  
  9.     }  
  10.  res.setTimeout(1000,function(){  
  11.     console.log('服务器端超时了');  
  12.     res.end();//结束  
  13.  })  
  14. }).listen(8888,'localhost');  
第二个参数就是为response添加的timeout事件。如果没有request,response,server注册timeout事件,如果超时了socket就会自动销毁,如果你给request,response,server添加timeout事件,那么你对于超时事件的处理就要全权负责!返回值是一个response!
问题10:response.statusCode

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     //如果没有通过response.writeHead()显式发送HTTP头,那么当响应头被刷新时候就会发送这个状态码!  
  4.     //客户端可以通过res.statusCode获取  
  5.   res.statusCode=404;  
  6.   res.end('结束');  
  7. }).listen(8888,'localhost');  
问题11:response.statusMessage

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     //如果没有通过response.writeHead()显式发送HTTP头,那么当响应头被刷新时候就会发送这个信息,如果  
  4.     //是undefined,那么就会发送默认status code的默认信息,如404表示'Not Found'  
  5.   res.statusMessage='404 Not Found';  
  6.   res.end('结束');  
  7. }).listen(8888,'localhost');  
问题12:response.write

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3. //方法签名为:response.write(chunk[, encoding][, callback])  
  4. //如果response.write被调用,但是 response.writeHead() 没有被调用,那么就会转化到隐式的头模式,然后刷新默认的headers头!  
  5. //这个方法可以多次调用从而提供完整的响应体  
  6. //第一个参数可以是string也可以是buffer,如果第一个是string那么第二个参数就是用什么编码把string转化为二进制流,默认是U8编码,第三个回调函数会在数据被刷新到客户端的时候调用  
  7. //注意:这是raw的http响应体,和一些high-level和multipart-part的编码没有关系  
  8. //第一次response.write会把缓存的头部信息和第一部分数据体给客户端,第二次response.write,Node.js会认为你要获取数据流,然后分开发送,所以响应会被缓存到数据体中!  
  9. //该方法如果所有的数据都被成功放入缓存就会返回true,如果部分数据依然在用户内存中就会返回false,当缓存空了就会触发drain方法  
  10.  res.write('hello');  
  11.   res.end('结束');  
  12. }).listen(8888,'localhost');  
问题13:response.writeContinue

发送 HTTP/1.1 100 Continue 消息给客户端,表示请求体可以发送。发送大文件的时候可以用!
问题14:response.writeHead(statusCode[, statusMessage][, headers])

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.  //方法签名为:response.writeHead(statusCode[, statusMessage][, headers])  
  4.  var name='我是高山上的鱼';  
  5.      res.writeHead(200, {  
  6.       'Content-Length': Buffer.byteLength(name,'utf8'),  
  7.       'Content-Type''text/plain' });  
  8.      //必须在response.end方法之前调用。而且Content.length是字节而不是字符,如果有非ASCII那么应该用  
  9.      //Buffer.byteLength方法  
  10.      res.end();  
  11. }).listen(8888,'localhost');  
注意:此处用了Buffer.byteLenght来获取一些非ASCII的字符串的字节长度,不是字符长度!
第二部分: Class: http.Server
注意:该类继承了net.Server,下面都是自己添加的一些方法和事件

问题1:checkContinue事件:

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3. //API签名:function (request, response) { }  
  4. //每次接收到Expect:100-continue就会触发,如果没有这个事件,那么服务器就会自动返回一个100 Continue  
  5. //这个事件和response.writeContinue有关,如果客户端能够继续发送消息。如果客户端不能继续发送那么就自己产生一个HTTP response,如400 Bad Request  
  6. //注意:如果这个事件触发了并且处理了,那么request事件不会触发!  
  7. }).listen(8888,'localhost');  
问题2:clientError事件

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     //API:function (exception, socket) { }  
  4.     //如果客户端连接触发了error事件,那么就会在这里被clientError事件处理  
  5.     //第二个参数是net.Socket实例  
  6. }).listen(8888,'localhost');  
问题3:close事件

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     //API:function () { }  
  4.     //如果服务器停止了就会触发close事件  
  5. }).listen(8888,'localhost');  
问题4:connect事件(通常在HTTP代理时候出现)

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     //API:function (request, socket, head) { }  
  4.     //客户端每次请求一个http的CONNECT方法的时候就会触发,如果这个方法没有注册事件,那么客户端对CONNECT方法的请求就会被关闭  
  5.     //request是http的request对象;socket是服务器端和客户端的套接字;head是一个BUffer实例  
  6.     //这个事件被触发以后,request的socket就不会有一个data事件监听器,所以如果你需要处理客户端的发送的消息那么应该自己注册!  
  7. }).listen(8888,'localhost');  
问题5:connection事件

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     //API:function (socket) { }  
  4.     //当一个新的TCP连接被建立的时候触发,socket是一个net.Socket的对象,一般情况下用户不需要这个事件。也可以用request.connection来设置  
  5. }).listen(8888,'localhost');  
问题6:request事件

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     //API:function (request, response) { }  
  4.     //每次request时候都会触发。注意:有时候一条连接可能有多个请求,如keep-alive情况下。request  
  5.     //参数是http.IncomingMessage,而response是http.serverResponse实例  
  6. }).listen(8888,'localhost');  
问题7:upgrade事件

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     //API:function (request, socket, head) { }  
  4.     //如果没有监听这个事件,那么client要求升级协议就会导致链接关闭  
  5.     //当这个事件触发了以后,那么请求的socket就不会有data事件监听器了,所以如果需要处理客户端发送的数据那么就会自己监听  
  6. }).listen(8888,'localhost');  
问题8:server.close方法

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.     server.close(function(){});  
  4.     //服务器不再接受新的连接!  
  5. }).listen(8888,'localhost');  
问题9:server.listen方法

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.    //API签名:server.listen(port[, hostname][, backlog][, callback])  
  4.    //port如果设置为0那么就会被设置为一个随机的port。这个方法是异步的,最后一个callback参会将会作为listening事件的监听函数  
  5. }).listen(8888,'localhost');  
问题10:listening和maxHeadersCount属性

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.    console.log(server.listening);  
  4.    //服务器是否在监听这个connection  
  5.    console.log(server.maxHeadersCount);  
  6.    //默认是1000,如果设置为0就是没有限制  
  7.    res.end();  
  8. }).listen(8888,'localhost');  
问题11:timeout属性和方法(如果设置为0那么就永远不会过时)

[javascript]  view plain  copy
  1. var http=require('http');  
  2. var server=http.createServer(function(req,res){  
  3.   //API:server.setTimeout(msecs, callback)  
  4.   //Server默认的timeout是2min,如果超时,socket会自动销毁。如果你传入了回调那么超时就必须自己负责,返回server实例  
  5.    //可以通过server.timeout进行设置,默认是120000  
  6.    console.log(server.timeout);  
  7.    res.end();  
  8. }).listen(8888,'localhost');  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值