仰望星空的天台

0%

NodeJs学习历程

nodejs

Hello World

首先要明白一点,每门语言的实现都需要一个解析器,尽管是同一门语言,

解析器不同就可能导致具体实现的功能不同,对于前端页面来说,解析器便是浏览器程序。 Ecmascript5 的用处是操作各种DOM结点来完成页面的各种功能、布局样式的修改和特效, 所以浏览器便提供了Document Object Model 和 Brower Object Model 来方便Ecmascript5 操纵页面

所以说在浏览器端,

由Ecmascript5 + DOM + BOM 就组成了我们所谓的Javascript

而在后端服务器方面

因为具体需要用来操作磁盘文件和搭建服务器,所以这时候的解析器就不是浏览器程序了。 而nodejs就充当了解析器这么一个角色

也就是说nodejs并不是一门语言,而是一个后端的解析器,或者说一种后端的运行环境

nodejs为了能让我们更好的完成它的用途也给我们提供了如 http , fs 等等的内置模块(类比DOM BOM)

nodejs可以说是前端人员了解后端的一个切入点所在(当然php也很适合) 这样前端人员就可以在他们的老本行的基础上调用封装好后端脚本框架了

配置sublime 快速编译

很简单(个人觉得比webstrom 简单)

只需要在sublime中找到

工具–>编译系统–>新编译系统

然后sublime就会弹出一个 untitled.sublime-build,将untitled 改成nodejs 然后再将里面原有的文本替换成

{
    "cmd": ["node", "$file"],
    "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
    "working_dir": "${project_path:${folder}}",
    "selector": "source.js",
    "shell": true,
    "encoding": "utf-8",
    "windows": {
        "cmd": ["node", "$file"]
    }
}

保存到默认的目录下,就可以了,sublime会自动检测已经安装好的nodeJS 然后再 工具–>编译系统–>自动编译

这样sublime 会根据程序来识别不同的script,进行不同编译

这样,当你写好一个js文件,只要直接 ctrl + b sublime 就会自动调用nodeJS进行编译

node基础

nodeJs 基础 和 js 基础一致,都是ecmascript

所以ecmascript底下的所有东西,都可以使用

var  a = new Date();
console.log( a.getFullYear() );
console.log( a.getMonth() + 1 );
console.log( a.getDate() );
console.log( a.getHours() );
console.log( a.getMinutes() );
console.log( a.getSeconds() );


var arr = [];

arr.push.apply( arr , [1,2,3] );
arr.push.apply( arr , [4,5,6] );
arr.push.apply( arr , [7,8,9] );

console.log(arr);

function run(name) {
	this.name = name;
}

run.prototype.runfuc = function() {
	console.log( this.name );
}

var b = new run('owen');
b.runfuc();

以上代码都可以编译运行

还有一点,就是在nodeJs中,最上层的对象不是window而是global global 也是ecmascript中定义的一个最上层的对象,但不对外访问,js中的window其实是global的一个引用

模块

nodejs实现功能是以不同个模块来完成的

nodejs规定一个js文件就是一个模块,不同模块有自己的作用域 我们使用var 在一个js文件里面声明的变量只是该模块下的局部变量 如果需要声明全局变量,我们可以使用global声明

global.a = 200;
console.log(global.a); // 200

我们还可以通过__filename变量来访问当前被解析模块的路径字符串 每一个模块中都有一个__filename

console.log(__filename); // D:\NodeJs\text\global-problem.js

还有一个__dirname变量 可以来访问当前被解析模块的文件夹路径字符串

console.log(__dirname); // D:\NodeJs\text\

模块加载系统

我们可以使用require来引入模块,类似java中的import

require('模块路径');

所引入的模块会自动被解析执行。

nodeJs的解析顺序是这样的

① 首先按照文件名来查找 ② 如果未找到,并且填写的路径中文件名没有带后缀的话,会自动加上.Js 的后缀,然后继续查找 ③ 如果还没找到,就会在文件名后缀加上.json ,继续查找 ④ 如果还是没找到,就会在文件名后缀加上.node,继续查找 ⑤ 如果还是没找到,就会报出一个错误

require('./text1');

例如如上代码,nodeJS会先在目录下查找text1文件,如果没有找到,就会自动在后面加上.js 然后按照text1.js来进行查找。

如果text1.js没找到,就会改成text1.json 进行查找 同理,还没找到就会改成 text1.node 进行查找

并且在nodejs中 是认可相对路径和绝对路径的

但是要注意一点,那就是,在node中,如果需要引入的文件在同目录下面 一定要这样写

require('./practice.js');

但是不能这样写

require('practice.js');

因为上述这样直接写文件名的方式,在nodeJS中会被认为是从核心模块(node_modules)中加载文件 而你的核心模块中没有practice.js 那么就会报错

module 对象

module 对象是每一个模块都特有的一个对象 例如这样一个模块 module1

// module1
var a = "owen";

console.log("这是module1");

我们可以console一下它的module

Module {
  id: '.',
  exports: {},
  parent: null,
  filename: 'D:\\NodeJs\\text\\module1.js',
  loaded: false,
  children: [],
  paths: 
   [ 'D:\\NodeJs\\text\\node_modules',
     'D:\\NodeJs\\node_modules',
     'D:\\node_modules' ] }

由此可以看到了,一个模块下包含如下属性 id : 可以标明一个模块的唯一标识 exports : 输出对象 parent : filename: 模块路径 loaded : children: 引入模块的模块对象的集合 paths :

模块作用域

一个模块中,如果要声明变量可以有这么几种方式

① 使用var 上面也说过了,这样声明的变量,作用域只在该模块内有效,如果这个模块被另一个模块加载了 那么另一个模块是无法访问使用var声明的变量的

② 使用global 在全局下使用在global对象下声明属性,这样变量的作用域就被提升到了全局范围,就不会出现加载后无法访问的问题,但是这样声明变量的方法不被推荐

③ 使用module.exports

例如如下两个模块

// module1
var a = "owen";

console.log("这是module1");

module.exports.a = a;
// 也可以这样写 exports.a = a;
// module2
var m1 = require("./module1.js");

console.log("这是module2");

console.log( m1.a ); // owen

当module2 中使用require引入了module1的时候会返回module1中模块对象下的exports 所以,只要在module1 中 将私有变量赋值给export对象的属性,就能够实现跨模块变量的访问

可以把一个模块类比为函数,exports就是其返回值

global.process

process(英:进程、过程) 对象是global 对象下的一个子对象,它可以在全局范围内被使用,访问的时候可以简写 process

process.argv

通过这个我们能访问,当前进程的一些内容

console.log( process.argv );

会返回一个数组,该数组中第一个值 是编译这个模块的编译器路径 第二个值 是这个模块的绝对路径(即 __filename)

之后的值就是执行模块的时候所带的参数

process.execPath

开启当前进程的这个可执行文件的绝对路径

process.env

返回用户环境信息(包括使用的操作系统 , 系统盘符 , 系统的根目录 …..)

process.version

返回当前node的版本信息

process.versions

返回当前node的版本信息,以及依赖包的版本信息

process.pid

返回进程的PID

process.title

返回进程的显示名称

process.arch

返回当前的处理器架构

还有很多process下的操作可以参考nodeJs手册

process下的IO流

Buffer(英:缓冲、缓冲器)

感觉后端的基础就是要对Buffer进行合适的操作

var bf = new Buffer(5); 
console.log(bf) // <Buffer 04 00 00 00 00>

打印出来的是5个随机的内存值,并且以16进制显现

但是如果我们将单个内存值打印出来,会以10进制显现

var bf = new Buffer(5); 
console.log(bf[0]) // 200

我们可以直接以字符串的形式直接存入缓存中,第二个参数声明的是字符串的编码

var bf = new Buffer('owen' , 'utf-8'); 

不同的编码形式所存储的字节数目是不同的 GB2312 一个英文为一字节 一中文为两字节 unicode 英文和中文都是两个字节 utf-8 因为为一字节 中文为三字节

声明一个有具体大小的缓存区,如未声明大小就会报错

Buffer.write

声明完缓存区域后,我们可以将值写入到缓存区

var bf = new Buffer(4); 
var str = 'owen';
bf.write(str);
console.log(bf.toString())  // owen

write方法一定要保证足够的缓存,如果没有开辟足够的内存,后面未存储的部分自动被抛弃 write 方法的第二个参数 是设置偏移量,即从第几个开始存储

var bf = new Buffer(4); 
var str = 'owen';
bf.write( str2 , 1 );      // 第二个参数可以设置偏移量,设置在第二位置开始存储
console.log(bf.toString());// 随机的乱码 owe

第三个参数是设置存储个数,即存储多少个字节

var bf  = new Buffer(6);
var str = 'owen';
bf.write( str , 1 , 2 );   // 第三个参数设置设置存储个数 , 默认是全部存储
console.log(bf);           // <Buffer 00 6f 77 00 00 00>

第四个参数设置写入的字符串编码

Buffer.toString

通过Buffer.toString方法与我们以前的toString方法有点不同

如果单个打印Buffer 缓存值可以带上进制参数

var str = 'owen';
var bf  = new Buffer(4);
console.log(bf[0].toString(8)) // 157 

如果直接整个buf (不带参数) 则会转化为字符号串

var str = 'owen';
var bf  = new Buffer(4);
console.log(bf.toString()) // owen 

如果有参数

第一个参数是字符编码 默认是 ‘utf-8’

第二三个参数是 设置偏移量 留始去终原则

var str = 'owen';
var bf  = new Buffer(4);
console.log(bf5.toString('utf-8' , 1 , 3)); // we

Buffer.toJSON

我们还可以将Buffer 打印成json格式

var bf = new Buffer("owen");
console.log(bf.toJSON() ); // 将buffer  转化为json格式

// 结果是
// { type: 'Buffer', data: [ 111, 119, 101, 110 ] }

第一个成员是类型 声明为Buffer 类型 第二个成员是data 数组 以10进制打印出来

Buffer.slice

和数组方法很像,但是有一点差别 首先使用都是相同的 都是留始去终原则

var bf1  = new Buffer("owen");
var bf2  = bf1.slice( 0 , 2 );

console.log(bf2.toString()); // ow

但是有一点就是,所切割的缓存部分不会开辟新的内存空间存储,只是开辟一个新的引用而已 也就是说,如果现在对bf2进行操作,会改变bf1的内容

var bf1  = new Buffer("owen");
var bf2 = bf1.slice( 0 , 2 );
console.log(bf1.toString()); // owen
bf2[0] = 0x65;               // 对剪切的第一个数进行赋值
console.log(bf1.toString()); // ewen

Buffer.copy

正如上文提到的,我们如果需要开辟新的内存进行对缓存的操作,不能使用slice 那么我们可以使用Buffer.copy来复制一份新的

var bf1 = new Buffer('owen');
var bf2 = new Buffer(2);
bf1.copy( bf2 , 0 , 0 , 3 ); 
console.log(bf2);               // <Buffer 6f 77>
console.log(bf2.toString());    // ow

切记被复制的buffer对象写在前面

静态Buffer方法

以上的方法,都是需要先构造Buffer实例才能进行的

Buffer对象是global 对象下的,所以也会有一些全局的静态方法

Buffer.isEncoding

判断是否是Buffer对象所支持的编码集

console.log( Buffer.isEncoding('utf-8') );  // true
console.log( Buffer.isEncoding('gbk') );    // false
console.log( Buffer.isEncoding('hex') );    // true

Buffer.isBuffer

判断是否是Buffer构造出来的实例

var arr = [1,2,3];
var bf  = new Buffer(3);

console.log( Buffer.isBuffer(arr) );
console.log( Buffer.isBuffer(bf) );

Buffer.byteLength

输出存储的字节长度

var str = "信管";
console.log(str.length);                        // 2
console.log(Buffer.byteLength(str));            // 默认的 utf-8下 是6
console.log(Buffer.byteLength(str1, 'ascii'));  // 2 如果使用不同的编码,返回的内存值也是不同的   

Buffer.concat

concat 以前数组里面也用过,就是连接两个数组的方法

var s1 = "owen love";
var s2 = " zyz";

var list = [new Buffer(s1),new Buffer(s2)]; 
var bf = Buffer.concat(list);
console.log(bf.toString());        // owen love zyz
console.log(Buffer.isBuffer(bf));  // true

但是,Buffer下的concat方法有点不同 , 接收一个数组 , 并且返回一个Buffer对象

而concat的第二个参数,是开辟新内存的大小,默认值是拼接的两个Buffer 内存量的总和 计算两个Buffer内存量 会消耗一部分内存 所以如果在知道值情况下应该尽量写上

var bf2 = Buffer.concat(list,13);
console.log(bf2.toString());

FileSystem

我们可以使用fileSystem 来控制本地文件

其中 fileSystem 很多方法都有同步和异步的区别 , 异步执行有回掉函数,同步执行则和我们平时的逻辑思维相同,按顺序执行,所以如果需要代码读写逻辑清晰可以使用同步的方法(Sync) 两种方式得到的结果都会是相同的。

fileSystem 是node内置的模块,所以我们在使用前只需要直接加载就行,nodejs的模块依赖会自动绑定

var fs = require("fs");

其中主要的方法就是 读 、 写 、 查询、 删除等操作文件夹和文件的方法,较为底层的方法我就不太过多缀余了,但是大家要清楚,所有对文件的操作,都是基于这些底层方法来实现的(write 、 read 、 open 、 access etc)

有兴趣的可以参考阅读nodejs 文档

readFile(Sync)

故名思意,就是读取文件,需要提供文件的文件目录

var fs = require("fs");

var filePath = "./";

fs.readFile(filePath , function (err , data) {
	err && console.log(err);

	console.log("文件内容是:" + data.toString("utf-8"));
})

或者使用异步的方式

var fs = require("fs");

var filePath = "./";

var file = fs.readFileSync(filePath);

console.log(file.toString("utf-8"));

writeFile(Sync)

写文件,也很简单

var fs = require("fs");

var filePath = "./";

fs.writeFile(filePath , "这是写入的内容" , function(err) {
	// 写完之后需要做的事儿
});

同步就少了个回调罢了

还有一点,如果所提供的路径没有文件,那么就会自动新建一个文件,并写入内容 并且,写方法会将原有的内容覆盖 要特别注意哦!

小功能(复制文件内容)

function copy ( src , dst ) {
    fs.writeFileSync( dst  , fs.readFileSync(src) )
}

function main ( argv ) {
    copy( argv[0] , argv[1] );
}

// 路径由终端参数传入, 第一个参数为被复制的文件(源), 第二个参数为复制的文件
所以,在复制前需要先在地址目录下创建一个文件
main( process.argv.slice(2) );

appendFile(Sync)

插入文件内容,不覆盖原有数据,如果没有文件会自动创建

var fs = require("fs");

var filePath = "./";

fs.appendFile(filePath , "这是写入的内容" , function(err) {
	// 插入完之后需要做的事儿
});

Caveats

① 第二个参数也可以是Buffer对象 ② 第三个参数可写可略,{ encoding : “xxx编码” , mode : “默认值0o666” , flag : “索引值 默认是a” }

readdir(Sync)

查询文件夹,并返回文件夹下的全部文件

var fs = require("fs");

var dirPath = "./";

fs.readdir(dirPath , function(err , files) {
	files.foreach( fname ) {
		console.log( fname );
	}
});

mkdir(Sync)

创建文件夹,和读差不多,但是可以设置新建文件夹的权限[第二个参数]

existsFile(Sync)

判断是否存在此文件,返回boolean

var fs = require("fs");

var filePath = "./";

fs.existsFile( filePath , function( isexists ) {
	// 判断是否存在 ,如果存在再写入文件

	if( isexists ) {
		fs.writeFile(filePath , "Owen" , function(err) {
			console.log("已覆盖原有文件");
		});
	}
});

link(Sync)

创建一个文件链接 ( srcPath , dstPath , callback )

srcPath : 源目录或文件的路径 dstPath : 存放转换后的目录的路径,默认为当前工作目录 callback: 回调

unlink(Sync)

删除文件或文件夹,要小心,以免删错,不然就找不回来了

var fs = require("fs");

var filePath = "./xxx";

fs.existsFile( filePath , function( isexists ) {
	// 判断是否存在 ,如果存在再进行删除

	if( isexists ) {
		fs.unlink(filePath ,  function(err) {
			err && console.log(err);
			console.log("已删除目标文件(夹)");
		});
	}
});

Watch(Sync)

可以查看文件(夹)发生了什么修改,会返回修改的状态, 状态分为 renamechange, 也就是判断文件(夹)改名了或内容被修改了 ,并且返回被修改的文件名称

var fs = require("fs");

var filePath = "./xxx";

fs.existsFile( filePath , function(err) {
	// 判断是否存在 ,如果存在再进行监听
	
	if( isexists ) {
		fs.watch(filePath ,  function( event , filename ) {
			console.log( "change event is :" + event );

			if( filenames ) {
				console.log( "The file Which be changed : " + filename  );
			} else {
				console.log( "no file be changed" );
			}
		});
	}
});

当然,我这里只是简单的对一个文件进行判断

Caveats

① Watch方法 的Api 是不完整的, 什么意思呢? 就是说在不同的操作系统下,会在某些原因(例如权限的禁止) 而无法使用

② 第二点就是Watch方法在默认情况下是禁止递归的(recursive),什么意思呢? 就是说,如果你查询的文件夹下的子文件夹下,如果有文件被修改了,也不会有提示有文件被修改,因为Watch方法在默认情况下,只是查询路径下的全部文件,其中的子文件夹内的文件不会递归的进行查询

如果需要进行递归查询的话呢,我们可以进行设置,就是在第二个参数中进行设置

var fs = require("fs");

var filePath = "./xxx";

var options = { persistent: true, recursive: true }; 

// 持续性(persistent) 意思就是当文件被检查状态的时候是否还继续运行,这里默认就是确定的
// 文档原文为:persistent that indicates whether the process should continue to run as long as files are being watched.

fs.existsFile( filePath , options , function( isexists ) {
	// 判断是否存在 ,如果存在再进行监听
	
	if( isexists ) {
		fs.watch(filePath ,  function( event , filename ) {
			console.log( "change event is :" + event );

			if( filenames ) {
				console.log( "The file Which be changed : " + filename  );
			} else {
				console.log( "no file be changed" );
			}
		});
	}
});

这里,直接把 recursive 是否进行递归,赋值true 就也会进行子文件夹下的内容判断了

watchFile

检查文件 函数

一共有三个参数, (文件名 , [设置项] , [callback] )

设置项是一个对象,可以设置文件在检查过程中是否持续进行(persistent) , 还有一个就是文件持续运行的时间区间(interval)以毫秒为单位, 因为是检查文件 而不是文件夹,就没有是否递归查询的选项(recursive)

回调函数 , 回调函数 会返回两个参数,现在的状态(current)之前的状态(prev)

这两个参数实际上是从属于fs.stat的,返回的文件的详细信息, current 自然不用说就是返回现在的文件信息, prev就是文件被访问前的文件信息 还有一个需要注意的地方,就是这个回调函数调用的时候是当有人访问了这个文件的时候,才会进行调用

总结来说就是,检查这个文件,并查看是否被修改,如果修改了,可以通过访问current的文件状态进行查询

realpath

我们可以使用这个方法 根据某个文件的相对路径 resolve 成绝对路径 底层实现是根据process.cwd

参数有三

(需要还原的路径 , [cache] , [callback])

fs.realpath("./" , cache , function (err , resovlePath) {
	console.log(resovlePath); // "D:\NodeJs\text"
});

Caveats

① 可以使用cache来进行强制还原 ,什么意思呢? 就是当是一些特殊路径的情况下,无法直接还原了,借鉴其他非特殊路径的文件,将他们的父级路径映射给需被还原的路径

官网example:

var cache = {'/etc':'/private/etc'};
fs.realpath('/etc/passwd', cache, function (err, resolvedPath) {
  if (err) throw err;
  console.log(resolvedPath);
});

stat(Sync)

返回一个文件(夹)的详细信息

( 文件(夹)路径, callback )

fs.stat(filename , function (err , stats) {
	if( !err )
	{
		console.log(stats);
	}
});

Caveats

① 其中 callback 可以返回一个 stats 这个对象里面包含该文件的各种数据,及其一些方法

stats.isFile() 检查是否是一个文件
stats.isDirectory() 是否是一个文件夹
stats.isBlockDevice() 
stats.isCharacterDevice()
stats.isSymbolicLink() (只用 fs.lstat() 才存在)
stats.isFIFO()
stats.isSocket() 

path模块

在node中,并不建议使用拼接字符串的方式处理路径字符串,建议采用path模块来处理路径字符串

normalize

这个方法可以将不合法的路径名格式化成合法的路径字符串

var path = require("path");

console.log(path.normalize('/foo/bar//baz/asdf/quux/..'));

// \foo\bar\baz\asdf

join

我们可以使用join方法对路径进行合并

var path = require("path");

console.log(path.join('///foo', 'bar', '//baz/asdf', 'quux', '..'));

// \foo\bar\baz\asdf

这个方法,可以将传入的所有字符串拼接成合法的字符串,并格式化

sep

我们可以通过这个属性,获得每个特定平台的特殊分隔符号

例如:在window下的分割符号 是 (\)

通过这个分隔符号,我们可以将特定的路径分隔为一个数组

var path = require("path");

'foo/bar/baz'.split(path.sep)

// returns ['foo', 'bar', 'baz']

parse

我们可以使用parse进行解析路径

console.log(path.parse('/home/user/dir/file.txt'))
// returns
// {
//    root : "/",
//    dir : "/home/user/dir",
//    base : "file.txt",
//    ext : ".txt",
//    name : "file"
// }

url 模块

我们可以使用url 模块来处理url 字符串

parse

var url =  require("url");

var __URL__ = "http://user:pass@host.com:8080/p/a/t/h?query=string#hash";

console.log( url.parse(__URL__) );

// Url {
//  protocol: 'http:',
//  slashes: true,
//  auth: 'user:pass',
//  host: 'host.com:8080',
//  port: '8080',
//  hostname: 'host.com',
//  hash: '#hash',
//  search: '?query=string',
//  query: 'query=string',
//  pathname: '/p/a/t/h',
//  path: '/p/a/t/h?query=string',
//  href: 'http://user:pass@host.com:8080/p/a/t/h?query=string#hash' }

可以返回一个对象,包含所解析的url的全部信息

format

使用format 方法可将一个url对象 格式化成标准的url地址

var urlObj =  {
 protocol: 'mailto',        // 如果没写:// 会自动添加
 slashes: true,
 auth: 'user:Owen',         // 如果出现就会被加入
 host: 'qzone.com:3000',    // 优先级最高
 port: '8080',              // 只有没有host 的时候,才会将使用port 属性
 hostname: 'host.com',      // 只有没有host 的时候,才会使用hostname属性
 hash: '11111111112222222', // 如果没有# 会自动添加#
 search: '?query=string',   // 优先级最高
 query: 'query=xxxxx',      // 如果没有search的时候,才会将query 属性使用
 pathname: '\/p\/a\/t\/h',
}

console.log(url.format(urlObj));
// mailto://user:Owen@qzone.com:3000/p/a/t/h?query=string#11111111112222222

小记: format 和 parse 就是一对孪生胞胎

resolve

Url 还有一个resolve方法

作用貌似是替换base路径

这是官方网站给的栗子

console.log(url.resolve('/one/two/three', 'four'))         // '/one/two/four'
console.log(url.resolve('http://example.com/', '/one'))    // 'http://example.com/one'
console.log(url.resolve('http://example.com/one', '/two')) // 'http://example.com/two'

简单的文件遍历算法

var fs = require("fs");

var arr = [];
function travel(dirname, callback) {

    fs.readdirSync(dirname).forEach(function (file) {
    	
    	var pathname = dirname + file + "/";
        
        if (fs.statSync(pathname).isDirectory()) {
            // 如果是文件夹,就继续遍历文件夹
            travel(pathname, callback);
        } else {
        	// 如果是文件的话,将文件名称传入回调函数,执行操作
            callback(pathname);
        }
    });
}

travel("需要遍历查询的文件夹名" , function(pathname){
	arr.push({"[文件路径]" : pathname});
});

console.log( arr );

该算法可以遍历一个文件夹,及其子文件内的全部文件并且,每遍历一个文件遍执行一次回调函数,通过这个遍历算法我们就可以比较方便的遍历并给被遍历的文件添加执行事件

简单的构建项目算法

var fs = require("fs");

// 预设项目信息
var programdata = {

	"name" : "program",
	"fileData" : [
				{	
					"name" : "css",
					"type" : "dir"
				},
				{	
					"name" : "js",
					"type" : "dir"
				},
				{	
					"name" : "images",
					"type" : "dir"
				},
				{	
					"name" : "index.html",
					"type" : "file",
					"content" : "<html>\n\t<head>\n\t\t<meta charset='utf-8'>\n\t\t<title>页面模板</title>\n\t</head>\n\n\t<body>\n\t</body>\n</html>"
				}
			]	
};
// 判断构建项目文件夹是否已经存在,如未存在建立项目文件夹
programdata.name && !fs.existsSync( programdata.name ) && fs.mkdir(programdata.name);

var fData = programdata.fileData;

// 判断fileData是否是对象
if( fData && fData.forEach ) {

// 循环建立项目
	fData.forEach( function( fInfo ) {
		fInfo.path = programdata.name + "/" + fInfo.name;
		
		fInfo.content = fInfo.content || "";

		switch( fInfo.type ) {
			case  "dir": 
				!fs.existsSync( "./" + fInfo.path ) && fs.mkdirSync( "./" + fInfo.path );
				break;

			case "file":
				fs.writeFileSync(  "./" + fInfo.path , fInfo.content , "utf-8");
				break;

			default:
				break;
		}

	}); 
}

搭建一个简单WebServer

首先使用前我们都需要这样加载这样一个http模块

var http = require('http');

这样我们就可以使用这个模块返回的对象来新建一个网络服务

// 创建一个本地服务环境,并设置端口为localhost:8888
var serve = http.createServer().listen(8888);

这个函数会返回一个回调函数,这个函数会产生两参数 分别存储用户请求的信息和方法服务器响应的数据和方法


// 回调匿名函数,并返回request 和 reponse
var serve = http.createServer( function( request , reponse ){
	
	// 我们可以在这个函数里面写一些监听响应事件
	
	respone.writeHeader( http状态码 , 头部信息声明(json形式) )

	// 一个脚本内只能有一个respone.end不然会报错

	respone.writeHeader( 200 , {'Content-Type' : 'text/html;charset="utf-8"'});
	respone.write("Hello World 欢迎");
	respone.end("该次响应请求已结束");

} ).listen(8888);

我们使用fs加载一个文件模块,通过文件模块我们可以根据客户端的请求来响应为用户提供对应的页面文件

var fs = require("fs");

通过fs.readFile() 来为用户提供不同的文件页面 调用这个函数需要传入两个参数 一个是请求的文件的路径(字符串) 一个是一个回调函数

这个回调函数返回两个参数,一个是 error错误信息参数,如果请求的内容没有找到或者出错, 就会返回一个包含错误信息的JSON回来

{ [Error: EISDIR: illegal operation on a directory, read] errno: -4068, code: 'EISDIR', syscall: 'read' }

如果并没有出错,则返回null

另一个获得的文件数据

如果获取成功获得的是一个xml的buffer标签,返回的是加密过的文件16进制编码 如果获取失败则得到的是null

一个简单的demo

// 加载http模块
var http = require('http');

// 建立完请求之后,执行回调函数 函数需要声明两个形参, request 和 respone

// 设置一个www文件记录下本站的根目录路径(www文件夹下可以放我们站内需要的页面文件和资源)
var documentRoot = 'D:/Wampserver/html5test/websockt/www'/

// fs加载文件模块
var fs = require('fs');

console.log( "Server running at http://localhost 8888 " );

var httpServer = http.createServer(function(request , respone)
{
	// request方法接收用户请求的内容
	// respone方法实现对用户请求服务器的发送
	
	console.log("有用户建立了访问");

	var url = request.url;

	var file = documentRoot + url;
	console.log('用户请求的文件路径' + file);
	
	// 读取文件
	fs.readFile( file , function( err , data )
	{
		if( err )
		{
			respone.writeHeader( 404 , {
				'content-Type' : 'text/html;charset="utf-8"'
			});
			respone.write("<h1>404错误</h1>")
			respone.end();
		}else{
			respone.writeHeader( 200 , {
				'content-Type' : 'text/html;charset="utf-8"'
			});
			respone.write( data );
			respone.end();
		}
		
	});	

}).listen(8888);

感谢

nodeJs

妙味课堂

在nodeJs 下部署功能模块

cNode 关于http模块基础

7天学会nodejs ?

npm包管理工具

粉丝日记

Table of Contents