Node.js基础学习之常见API理解

问题1:process.exit事件

process.on('exit', function(code)  {
  // 这里必须只能是同步代码快,而不能是异步的
  setTimeout(function() {
    console.log('This will not run');
  }, 0);
  console.log('About to exit with code:', code);
});
(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事件

process.on('uncaughtException', function(err){
  console.log(`Caught exception: ${err}`);
});
setTimeout(function() {
  console.log('This will still run.');
}, 500)
// Intentionally cause an exception, but don't catch it.
nonexistentFunc();//异常被捕获,然后退出
console.log('This will not run.');

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

问题4:unhandledRejection事件

process.on('unhandledRejection', function(reason, p) {
    console.log("Unhandled Rejection at: Promise ", p, " reason: ", reason);
    // application specific logging, throwing an error, or other logic here
});
var Q = require('q');
//获取defer
 var deferred = Q.defer();
  deferred.reject('你没有权限');

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

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

问题5:SIGN Event事件

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

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

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

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

// print process.argv
process.argv.forEach(function(val, index, array) {
  console.log(`${index}: ${val}`);
});
如果控制台打印:node argv.js qinliang sex=male 21

结果为:

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

console.log(`Starting directory: ${process.cwd()}`);
//${process.cwd()}获取当前的目录
try {
  process.chdir('/tmp');
  console.log(`New directory: ${process.cwd()}`);
}
catch (err) {
  console.log(`chdir: ${err}`);
}
问题9:process.config获取当前node.js执行的一些配置

console.log(process.config);
问题10:process.connected

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

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

问题12:process.env

console.log(process.env);

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

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

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

process.env.name= 'qinlaing';
console.log(process.env.name);//打印'qinliang'
通过delete可以删除process.env上的变量

   process.env.TEST = 1;
   delete process.env.TEST;
   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中输入:

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

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

var time = process.hrtime();
// [ 1800216, 25 ]
setTimeout(function(){
  var diff = process.hrtime(time);
  // [ 1, 552 ]
 //diff[0]表示的是秒,而第二个diff[1]表示的是纳秒!
  console.log('benchmark took %d nanoseconds', diff[0] * 1e9 + diff[1]);
  // benchmark took 1000000527 nanoseconds
}, 1000);

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

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

process.on('SIGHUP', function() {
  console.log('Got SIGHUP signal.');
});
setTimeout(function(){
  console.log('Exiting.');
  process.exit(0);
}, 100);
console.log('window中的pid为:'+process.pid);
//打印5664
process.kill(process.pid, 'SIGHUP');
//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

console.log(process.mainModule);
process.mainModule将会返回如下的信息

Module {
  id: '.',
  exports: {},
  parent: null,
  filename: 'C:\\Users\\Administrator\\Desktop\\nodeJS\\process\\mainModule.js',
  loaded: false,
  children: [],
  paths:
   [ 'C:\\Users\\Administrator\\Desktop\\nodeJS\\process\\node_modules',
     'C:\\Users\\Administrator\\Desktop\\nodeJS\\node_modules',
     'C:\\Users\\Administrator\\Desktop\\node_modules',
     'C:\\Users\\Administrator\\node_modules',
     'C:\\Users\\node_modules',
     '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表示堆内存中使用的内存量。

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

console.log('start');
process.nextTick(function() {
  console.log('nextTick callback');
});
console.log('scheduled');

打印如下结果:

start
scheduled
nextTick callback

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

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

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

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

console.log(`This process is pid ${process.pid}`);
//进程的pid值
console.log(`This platform is ${process.platform}`);
//进程指定的平台'darwin', 'freebsd', 'linux', 'sunos' or 'win32'
问题22:process.release

{ name: 'node', //node.js下是node
  sourceUrl: 'https://nodejs.org/download/release/v5.7.1/node-v5.7.1.tar.gz',//taz.gz文件包含当前的release
  headersUrl: 'https://nodejs.org/download/release/v5.7.1/node-v5.7.1-headers.ta
r.gz',
  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

process.stdin.setEncoding('utf8');
//设置输入的流的编码
process.stdin.on('readable', function(){
	//为process.stdin注册事件readable
  var chunk = process.stdin.read();
  if (chunk !== null) {
    process.stdout.write(`data: ${chunk}`);
  }
});
//为process.stdin注册end事件
process.stdin.on('end', function()  {
  process.stdout.write('end');
});

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

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

var newmask = 0o022;
//如果为process.unmask指定了参数那么返回值就是oldmask,也就是原来的掩码
var oldmask = process.umask(newmask);
console.log(
  `Changed umask from ${oldmask.toString(8)} to ${newmask.toString(8)}`
);

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

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

console.log(process.uptime());
//node.js已经运行的时间
console.log(process.version);
//内置的属性,反映node版本号,如v5.7.1
console.log(process.versions);
//内置的版本号和依赖
process.versions还可以打印node.js的依赖

{ http_parser: '2.6.2',
  node: '5.7.1',
  v8: '4.6.85.31',
  uv: '1.8.0',
  zlib: '1.2.8',
  ares: '1.10.1-DEV',
  icu: '56.1',
  modules: '47',
  openssl: '1.0.2g' }

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

下面是FileSystem模块相关知识:

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

var fs=require('fs');
//获取文件加载模块,用于监听当前目录的文件的变化
fs.watch('./', function(event, filename){
  console.log(`event is: ${event}`);
  if (filename) {
    console.log(`filename provided: ${filename}`);
  } else {
    console.log('filename not provided,  please check');
  }
});
(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)

var fs=require('fs');
fs.watchFile('readMe', function(curr, prev) {
  console.log(`the current mtime is: ${curr.mtime}`);
  console.log(`the previous mtime was: ${prev.mtime}`);
});

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

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

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

var fs=require('fs');
fs.access('./file.js', fs.R_OK | fs.W_OK, function(err) {
  console.log(err ? 'no access!' : 'can read/write');
});

(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])

var fs=require('fs');
//读取流
fs.createReadStream('sample.txt', {start: 90, end: 99});

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

{
  flags: 'w',
  defaultEncoding: 'utf8',
  fd: null,
  mode: 0o666,
  autoClose: true
}

(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)

var fs=require('fs');
fs.appendFile('./test','data to append',function(err){
	if(err)throw err;
	console.log('data appended!');
})

(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对象,该对象有以下属性:

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

属性说明如下表:

数字下标
关联键名(自 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
所占据块的数目

用法如下:

var fs=require('fs');
fs.stat('./file.js',function(err,stats){
	//其中stats是一个 fs.Stats对象
	console.log(stats);
})

(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)

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

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

var fs=require('fs');
//chown就是change owner的缩写把,改变文件的所有权,第二个参数是user id
fs.chown('file.js', 1, 2, function(err){
 if(err){
  console.log(err);
 }else{
  console.log("change done");
 }
})

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

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

var fs=require('fs');
//通过文件描述符来更改文件所有权,第二个参数是'a'表示是追加
fs.open('file.js', 'a', function (err, fd) { 
	 if (err) { 
	  throw err; 
	 } 
	 //通过文件描述符来修改
 fs.fchown(fd, 1, 2, function(err){ 
	  if (err) { 
	   throw err; 
	  } 
  	console.log('fchmod complete'); 
  	//这时候必须手动关闭文件描述符
	  fs.close(fd, function () { 
	   console.log('Done'); 
	  }); 
 }) 
});
(1)用于使用文件描述符来修改文件的所有权,但是必须注意,必须手动关闭文件描述符
(2)这里的fchown第一个参数是error对象

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

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

问题1:response.addTrailers方法

var http=require('http');
var server=http.createServer(function(req,res){
	//最大连接数是10,超过拒绝!
	server.MaxConnections=10;
	//获取连接数
     console.log(server.connections);
	res.writeHead(200,{'Content-Type':'text/plain','Trailer':'Content-MD5'});
	res.write('I am the data from server');
	res.addTrailers({'Content-MD5':'7895bf4b8828b55ceaf47747b4bca667'});
        //调用end方法
	res.end('我是qinl');
}).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那么会在响应流结束后调用回调

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

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

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

var http=require('http');
var server=http.createServer(function(req,res){
	   res.setHeader('Name','MoutainFish');
	var header=res.getHeader('Name');
		console.log(res.headersSent);
		//打印false
      res.writeHead(200);
	console.log(res.headersSent);
	 //打印true
	//显示调用end方法
	  res.end();
}).listen(8888,'localhost');
注意:在writeHead之前是false,之后是true
问题6:response.removeHeader

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

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

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

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

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

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

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

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

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

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

问题1:checkContinue事件:

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

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

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

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

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

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

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

var http=require('http');
var server=http.createServer(function(req,res){
	server.close(function(){});
	//服务器不再接受新的连接!
}).listen(8888,'localhost');
问题9:server.listen方法

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

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

var http=require('http');
var server=http.createServer(function(req,res){
  //API:server.setTimeout(msecs, callback)
  //Server默认的timeout是2min,如果超时,socket会自动销毁。如果你传入了回调那么超时就必须自己负责,返回server实例
   //可以通过server.timeout进行设置,默认是120000
   console.log(server.timeout);
   res.end();
}).listen(8888,'localhost');

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一部分 深入理解DOM脚本编程  第1章 遵循最佳实践    1.1 不唐突和渐进增强    1.2 让JavaScript运行起来     1.2.1 把行为从结构中分离出来     1.2.2 不要版本检测     1.2.3 通过平稳退化保证可访问性     1.2.4 为重用命名空间而进行规划     1.2.5 通过可重用的对象把事情简化     1.2.6 一定要自己动手写代码    1.3 JavaScript语法中常见的陷阱     1.3.1 区分大小写     1.3.2 单引号与双引号      1.3.3 换行     1.3.4 可选的分号和花括号     1.3.5 重载(并非真正的重载)     1.3.6 匿名函数     1.3.7 作用域解析和闭包     1.3.8 迭代对象     1.3.9 函数的调用和引用(不带括号)    1.4 实例:WYSIWYGJavaScript翻转图    1.5 小结   第2章 创建可重用的对象    2.1 对象中包含什么     2.1.1 继承     2.1.2 理解对象成员     2.1.3 window对象中的一切     2.1.4 理解作用域和闭包是根本    2.2 创建你自己的对象     2.2.1 一变多:创建构造函数     2.2.2 添加静态方法     2.2.3 向原型中添加公有方法     2.2.4 公有、私有、特权和静态成员真那么重要吗     2.2.5 对象字面量    2.3 this是什么    2.4 try{}、catch{}和异常处理    2.5 实例:你自己的调试日志     2.5.1 为什么需要JavaScript日志对象     2.5.2 myLogger()对象    2.6 小结   第3章 DOM2核心和DOM2 HTML    3.1 DOM不是JavaScript,它是文档    3.2 DOM的级别     3.2.1 DOM 0 级     3.2.2 DOM 1 级     3.2.3 DOM 2 级     3.2.4 DOM 3 级     3.2.5 哪个级别适合你    3.3 创建示例文档     3.3.1 创建DOM文件     3.3.2 选择一个浏览器   3.4 DOM核心     3.4.1 继承在DOM中的重要性     3.4.2 核心Node对象     3.4.3 核心Element对象     3.4.4 核心Document对象     3.4.5 遍历和迭代DOM树    3.5 DOM HTML     3.5.1 DOM2 HTML 的HTMLDocument对象     3.5.2 DOM2 HTML 的HTMLElement对象    3.6 实例:将手工HTML代码转换为DOM代码     3.6.1 DOM生成工具的HTML文件     3.6.2 使用示例HTML片段进行测试     3.6.3 扩充ADS库     3.6.4 generateDOM对象的框架    3.7 小结   第4章 响应用户操作和事件    4.1 DOM2级事件    4.2 事件的类型     4.2.1 对象事件     4.2.2 鼠标移动事件     4.2.3 鼠标单击事件     4.2.4 键盘事件     4.2.5 表单相关的事件     4.2.6 针对W3C DOM的事件     4.2.7 自定义事件    4.3 控制事件流和注册事件侦听器     4.3.1 事件流     4.3.2 注册事件     4.3.3 在事件侦听器中访问事件对象     4.3.4 跨浏览器的事件属性和方法    4.4 小结   第5章 动态修改样式和层叠样式表    5.1 W3CDOM2样式规范     5.1.1 CSSStyleSheet对象     5.1.2 CSSStyleRule对象     5.1.3 CSSStyleDeclaration对象     5.1.4 支持的匮乏    5.2 当DOM 脚本遇到样式    5.3 把样式置于DOM脚本之外     5.3.1 style属性     5.3.2 基于className切换样式     5.3.3 切换样式表     5.3.4 修改CSS规则    5.4 访问计算样式    5.5 Microsoft的filter属性    5.6 实例:简单的渐变效果    5.7 小结   第6章 案例研究:图像裁剪和缩放工具    6.1 测试文件    6.2 imageEditor对象     6.2.1 调用imageEditor工具     6.2.2 imageEditor载入事件     6.2.3 创建编辑器标记和对象     6.2.4 向imageEditor对象添加事件侦听器     6.2.5 缩放图像     6.2.6 裁剪图像     6.2.7 未完成的图像编辑器    6.3 小结  第二部分 浏览器外部通信  第7章 向应用程序中加入Ajax    7.1 组合的技术     7.1.1 语义化XHTML和DOM     7.1.2 JavaScript和XMLHttpRequest对象     7.1.3 XML     7.1.4 一个可重用的对象     7.1.5 Ajax是正确的选择吗    7.2 为什么Ajax会破坏网站及如何解决     7.2.1 依赖JavaScript生成内容     7.2.2 通过script标签绕过跨站点限制     7.2.3 后退按钮和书签功能     7.2.4 完成请求的赛跑     7.2.5 增加资源占用     7.2.6 问题解决了吗    7.3 实例:Ajax增强的相册    7.4 小结   第8章 案例研究:实现带进度条的异步文件上传功能    8.1 信息载入时的小生命    8.2 起点    8.3 完成整合:上传进度指示器     8.3.1 addProgressBar()对象的结构     8.3.2 载入事件     8.3.3 addProgressBar()对象    8.4 小结  第三部分 部分高级脚本编程资源  第9章 通过库来提高生产力    9.1 选择合适的库    9.2 增强DOM操作能力     9.2.1 连缀语法     9.2.2 通过回调函数进行过滤     9.2.3 操纵DOM文档    9.3 处理事件     9.3.1 注册事件     9.3.2 自定义事件    9.4 访问和操纵样式    9.5 通信    9.6 小结   第10章 添加效果增强用户体验    10.1 自己动手实现效果     10.1.1 让我看到内容     10.1.2 提供反馈    10.2 几个视觉效果库简介    10.3 视觉盛宴     10.3.1 MOO式的CSS属性修改     10.3.2 通过Script.aculo.us实现视觉效果     10.3.3 通过Moo.fx实现逼真的运动效果     10.3.4 圆角效果     10.3.5 其他库    10.4 行为增强    10.5 小结   第11章 丰富的Mashup!运用API添加地图、搜索及更多功能    11.1 API密钥    11.2 客户端API:离不开JavaScript     11.2.1 地图中的Mashup应用     11.2.2 Ajax搜索请求     11.2.3 地图与搜索的Mashup应用    11.3 服务器端API:需要代理脚本     11.3.1 通过Basecamp构建集成的To-Do列表     11.3.2 通过Flickr取得个性头像    11.4 小结   第12章 案例研究:用DOM设计选择列表    12.1 经典的感觉    12.2 构建更好的选择列表    12.3 策略?我们不需要臭哄哄的策略     12.3.1 相关的文件     12.3.2 FauxSelect对象     12.3.3 开始创建人造select元素     12.3.4 查找select元素     12.3.5 构建DOM元素    12.4 添加事件——为人造select赋予生命    12.5 让表单绽放光彩    12.6 行为修正     12.6.1 z-index来救急     12.6.2 键盘控制及其他细节     12.6.3 select太大了吗    12.7 最后的细节    12.8 继续替换select的冒险    12.9 小结
对于想要学习 Node.js 的人来说,以下是一个常见学习路线: 1. 入门基础知识:首先了解 JavaScript 的基础知识,包括变量、控制流、函数等等。可以通过在线教程、书籍或视频课程学习。 2. 了解后端开发概念:学习关于服务器端开发的基本概念,例如 HTTP、网络通信、数据库等。 3. 学习 Node.js 基础:通过官方文档或在线教程学习 Node.js基础知识,包括安装、模块系统、事件驱动编程等。 4. 掌握核心模块:了解和熟悉 Node.js 的核心模块,例如 fs、http、path 等,以便能够构建简单的服务器应用程序。 5. 学习 Express 框架:Express 是一个流行的 Node.js Web 框架,学习它可以帮助你构建更复杂的 Web 应用程序。可以阅读官方文档或参考教程来学习 Express。 6. 学习数据库集成:了解如何在 Node.js 中使用数据库,例如 MongoDB 或 MySQL。学习数据库连接、CRUD 操作等。 7. 异步编程:深入理解 Node.js 的异步编程模型,包括回调函数、Promise、async/await 等。 8. 学习 RESTful API 设计:了解如何设计和构建符合 RESTful 风格的 API。 9. 深入学习和探索:根据个人兴趣和需求,学习其他 Node.js 相关的技术、工具和框架,例如 WebSocket、GraphQL、Socket.io 等。 记住,这只是一个大致的学习路线,你可以根据自己的兴趣和需求进行调整和扩展。实践对于学习 Node.js 来说非常重要,所以尽量多做一些实际项目来巩固所学知识。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值