目录
node.js是基于v8引擎(chrome 8)的一个事件驱动I/O服务端JavaScript环境
上手:
require指令用于引用模块,在此处我们引用一个http的模块,并且赋值给http变量。
之后调用该模块来写一个demo:
var http = require('http');
http.createServer(function(request,response){
response.writeHead(200,{'Content-Type':'text/plain'});
response.end('hello world\n');
}).listen(8888);
console.log('server running at :8888');
该段代码写了一个简易的http服务器,在8888端口运行了一个helloworld程序,
NPM使用
npm是一个跟随node.js一起安装的包管理工具,类似于python的pip。
npm -v //查看版本
使用npm安装模块:
npm install <Module Name>npm install express
var express = require('express'); // 安装完成后的引用方法,与python别无二致,区别为关键词不同而已
全局安装与本地安装的区别:
npm install express # 本地安装 npm install express -g # 全局安装
本地安装:
将安装包放在./node_modules 下(运行 npm 命令时所在的目录),如果没有 node_modules 目录,会在当前执行 npm 命令的目录下生成 node_modules 目录。
以通过 require() 来引入本地安装的包。
全局安装:
将安装包放在 /usr/local 下或者你 node 的安装目录。
可以直接在命令行使用命令运行
查看现在有的全部全局安装(-g)信息:
npm list -g
package.json文件:
该文件记录了很多关于模块的有用信息(使用时的入口,关键字)
-
name - 包名。
-
version - 包的版本号。
-
description - 包的描述。
-
homepage - 包的官网 url 。
-
author - 包的作者姓名。
-
contributors - 包的其他贡献者姓名。
-
dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下。
-
repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上。
-
main - main 字段指定了程序的主入口文件,require('moduleName') 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js。
-
keywords - 关键字
卸载模块:
npm uninstall express
更新模块:
npm update express
搜索模块:
npm search express
node.js REPL
R(read)、E(evaluate)、P(print)、L(loop)是其全称。
-
读取 - 读取用户输入,解析输入的 Javascript 数据结构并存储在内存中。
-
执行 - 执行输入的数据结构
-
打印 - 输出结果
-
循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。
类似于python的shell,或者任何的shell。
进入REPL的方式为命令node,不再累述。
node.js 回调函数
node的异步编程特点就是回调函数,所有的api都有回调函数。
我们在执行一个i/o任务的时候,线程会被堵塞,这时使用回调函数即可,先进行读取操作之后执行后续操作,等读取完成就会触发回调函数机制。
回调函数一般作为最后一个参数出现。
堵塞读取文件:
var fs = require("fs");
var data = fs.readFileSync('input.txt');
console.log(data.toString());
console.log("完成");
该段代码在读取文件的时候就会堵塞住线程,虽然因为速度问题我们并不能看见,但其实在读取的时候是有堵塞的。
非堵塞读取文件:
var fs = require("fs");
var data = fs.readFile('input.txt',function(err,data){
if (err) return console.log(err);
console.log(data.toString());
});
console.log("完成");
该段代码定义了读取文件的回调函数,在我们执行的时候它不会造成堵塞,会自己在读取完成的时候调用回调函数,因此该段代码的结果先打印出完成
node.js事件循环
Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。
Node.js 几乎每一个 API 都是支持回调函数的。
Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。
Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.
Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。
当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。
这个模型非常高效可扩展性非常强,因为 webserver 一直接受请求而不等待任何读写操作。(这也称之为非阻塞式IO或者事件驱动IO)
在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。
node.js EventEmitter
node里的所有异步i/o操作在完成的时候都会向事件队列发送一个事件。
许多对象都会分发事件,一个 net.Server 对象会在每次有新连接时触发一个事件, 一个 fs.readStream 对象会在文件被打开的时候触发一个事件。 所有这些产生事件的对象都是 events.EventEmitter 的实例。
var events = require("events");
var emitter = new events.EventEmitter();
emitter.on("some_event",function(){
console.log("一些事件触发");
});
setTimeout(function(){
emitter.emit("some_event")
},1000);
建立的该事件监听器在本质上就是回调函数,之后1000毫秒后向事件队列发送该监听器,主线程会去执行它。
换而言之当我们触发事件时,事件便将回调函数添加至事件队列当中。
大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。
为什么要这样做呢?原因有两点:
首先,具有某个实体功能的对象实现事件符合语义, 事件的监听和发生应该是一个对象的方法。
其次 JavaScript 的对象机制是基于原型的,支持 部分多重继承,继承 EventEmitter 不会打乱对象原有的继承关系。
node.js Buffer(缓冲区)
JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。
但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。
在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。
编码:
var test = Buffer.from("test","ascii");
console.log(test.toString("base64"));
console.log(test.toString("utf-8"));
console.log(test.toString("hex"));
node现在支持的字符编码:
-
ascii - 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。
-
utf8 - 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。
-
utf16le - 2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。
-
ucs2 - utf16le 的别名。
-
base64 - Base64 编码。
-
latin1 - 一种把 Buffer 编码成一字节编码的字符串的方式。
-
binary - latin1 的别名。
-
hex - 将每个字节编码为两个十六进制字符。
其余操作详细请看:Node.js Buffer(缓冲区) | 菜鸟教程
node.js Steam
Stream 是一个抽象接口,Node 中有很多对象实现了这个接口。例如,对http 服务器发起请求的request 对象就是一个 Stream,还有stdout(标准输出)。
Node.js,Stream 有四种流类型:
-
Readable - 可读操作。
-
Writable - 可写操作。
-
Duplex - 可读可写操作.
-
Transform - 操作被写入数据,然后读出结果。
所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有:
-
data - 当有数据可读时触发。
-
end - 没有更多的数据可读时触发。
-
error - 在接收和写入过程中发生错误时触发。
-
finish - 所有数据已被写入到底层系统时触发。
从数据流当中读取:
var fs = require("fs");
var data = '';
var Streamreader = fs.createReadStream("input.txt");
Streamreader.setEncoding("UTF8");
Streamreader.on("data",function(temp){
data += temp;
});
Streamreader.on("end",function(){
console.log(data);
});
Streamreader.on("error",function(err){
console.log(err);
});
console.log("just test");
向数据流当中写入:
var fs = require("fs");
var data = 'hello tron';
var Streamwrite = fs.createWriteStream("input.txt");
Streamwrite.write(data,"UTF8");
Streamwrite.end();
Streamwrite.on("finish",function(){
console.log("finish");
});
Streamwrite.on("error",function(err){
console.log(err);
})
console.log("just test");
流的管道(实现对流的传递):
该操作先读取了input文件当中的流,之后通过管道将其传递给了output文件。
var fs = require("fs");
var Streamwrite = fs.createWriteStream("output.txt");
var Streamreader = fs.createReadStream("input.txt");
Streamreader.pipe(Streamwrite);
console.log("finish");
node.js模块系统
为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。
模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C++ 扩展。
demo:
module_1.js:
exports.world = function(){
console.log("hello world");
};
test_module.js:
var hello = require("./module_1");
hello.world();
代码require那段引入了当前目录下的module_1.js文件
Node.js 提供了 exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。
通过 exports 对象把 world 作为模块的访问接口,在 main.js 中通过 require('./module_1) 加载这个模块,然后就可以直接访问 exports 对象的成员函数了。
对象的模块化:
demo:
module_2.js:
function hello(){
this.setname = function(name){
this.name = name;
}
this.printname = function(){
console.log(this.name);
}
};
module.exports = hello;
test_module.js:
var hello = require("./module_2");
var h1 = new hello();
h1.setname("tron");
h1.printname();
这里定义模块的时候使用module.exports代替了exports.hello。二者的不同之处是:exports输出的对象就是exports,而module.exports = hello直接输出的是hello。
node.js的require查找策略:
require的内部加载总共有四步:
1先寻找文件模块缓存区当中有没有
2判断是否为原生模块
3判断是否在原生模块缓存区当中
4所有都不满足则从本地加载文件模块,根据拓展名载入。
参考:
1. 如果 X 是内置模块 a. 返回内置模块 b. 停止执行 2. 如果 X 以 '/' 开头 a. 设置 Y 为文件根路径 3. 如果 X 以 './' 或 '/' or '../' 开头 a. LOAD_AS_FILE(Y + X) b. LOAD_AS_DIRECTORY(Y + X) 4. LOAD_NODE_MODULES(X, dirname(Y)) 5. 抛出异常 "not found" LOAD_AS_FILE(X) 1. 如果 X 是一个文件, 将 X 作为 JavaScript 文本载入并停止执行。 2. 如果 X.js 是一个文件, 将 X.js 作为 JavaScript 文本载入并停止执行。 3. 如果 X.json 是一个文件, 解析 X.json 为 JavaScript 对象并停止执行。 4. 如果 X.node 是一个文件, 将 X.node 作为二进制插件载入并停止执行。 LOAD_INDEX(X) 1. 如果 X/index.js 是一个文件, 将 X/index.js 作为 JavaScript 文本载入并停止执行。 2. 如果 X/index.json 是一个文件, 解析 X/index.json 为 JavaScript 对象并停止执行。 3. 如果 X/index.node 是一个文件, 将 X/index.node 作为二进制插件载入并停止执行。 LOAD_AS_DIRECTORY(X) 1. 如果 X/package.json 是一个文件, a. 解析 X/package.json, 并查找 "main" 字段。 b. let M = X + (json main 字段) c. LOAD_AS_FILE(M) d. LOAD_INDEX(M) 2. LOAD_INDEX(X) LOAD_NODE_MODULES(X, START) 1. let DIRS=NODE_MODULES_PATHS(START) 2. for each DIR in DIRS: a. LOAD_AS_FILE(DIR/X) b. LOAD_AS_DIRECTORY(DIR/X) NODE_MODULES_PATHS(START) 1. let PARTS = path split(START) 2. let I = count of PARTS - 1 3. let DIRS = [] 4. while I >= 0, a. if PARTS[I] = "node_modules" CONTINUE b. DIR = path join(PARTS[0 .. I] + "node_modules") c. DIRS = DIRS + DIR d. let I = I - 1 5. return DIRS
node.js函数
node当中的函数与JavaScript函数的使用方法基本上一致。
不再累述
node.js路由
我们要为路由提供请求的 URL 和其他需要的 GET 及 POST 参数,随后路由需要根据这些数据来执行相应的代码。
我们需要查看 HTTP 请求,从中提取出请求的 URL 以及 GET/POST 参数。这一功能应当属于路由还是服务器(甚至作为一个模块自身的功能)确实值得探讨,但这里暂定其为我们的HTTP服务器的功能。
这里写一个简单的路由demo
首先定义服务文件(http服务):
var http = require("http");//引用http模块
var url = require("url");//引用url解析模块
function start(){//定义start函数
function onrequest(request,response){//定义一个创建服务时的函数
var pathname = url.parse(request.url).pathname;//解析请求的路径
if(pathname!="/favicon.ico")console.log("request by "+pathname);//去掉没用的访问路径
response.writeHead(200,{"Content-Type":"text/plain"});
response.write("hello world");//页面内容
response.end();
}
http.createServer(onrequest).listen(8888);//创建服务并且监听8888端口
console.log("it's begin");
}
exports.start = start;//定义该函数为exports输出的一个方法,模块使用
这样我们首先创建了一个http服务
写一个路由文件:
function route(pathname){
console.log("route a request:"+pathname);
}
exports.route = route;
这里的路由是没有任何作用或者对路径进行区分。
最终我们在main.js当中调用这两个模块
var Server = require("./server");
var Router = require("./router");
Server.start(Router.route);
我个人理解这里的路由应该有很多参数要进行设置,比如response这个对象是一定要进行传参处理的,否则是没办法对页面进行路由判断来更改。目前这里理解这一思想启动服务的时候只是写在一个函数里面,无法通过路由做任何事情。
node.js全局对象
global 最根本的作用是作为全局变量的宿主。按照 ECMAScript 的定义,满足以下条 件的变量是全局变量:
- 在最外层定义的变量;
- 全局对象的属性;
- 隐式定义的变量(未定义直接赋值的变量)。
全局对象的属性就是全局变量
在nodejs当中是无法从最外层定义变量的,因为所有的用户代码都是属于当前模块而不是最外层。
几个重要的全局变量:
__filename:
返回的是文件所在位置的绝对路径:
// 输出全局变量 __filename 的值 console.log( __filename );node main.js /web/com/runoob/nodejs/main.js
__dirname:
返回的是当前执行脚本的目录(区别于上一个原因是上一个可能在模块当中,输出的是模块的路径,而这个全局变量是当前执行脚本的路径)
node main.js /web/com/runoob/nodejs
setTimeout(cb,ms):
这是一个全局函数,其两个参数为在ms毫秒执行cb函数,只执行一次
demo:
function printHello(){
console.log( "Hello, World!");
}
// 两秒后执行以上函数
setTimeout(printHello, 2000);
clearTimeout(t):
这是一个全局函数,清除之前所通过setTimeout创建的定时器
setInterval(cb,ms):
该所有东西与setTimeout基本一致,只不过这是重复执行的一个全局函数,会不停的调用cb函数。
console:
console 用于提供控制台标准输出,它是由 Internet Explorer 的 JScript 引擎提供的调试工具,后来逐渐成为浏览器的实施标准
以下为 console 对象的方法:
序号 | 方法 & 描述 |
---|---|
1 | console.log([data][, ...]) 向标准输出流打印字符并以换行符结束。该方法接收若干 个参数,如果只有一个参数,则输出这个参数的字符串形式。如果有多个参数,则 以类似于C 语言 printf() 命令的格式输出。 |
2 | console.info([data][, ...]) 该命令的作用是返回信息性消息,这个命令与console.log差别并不大,除了在chrome中只会输出文字外,其余的会显示一个蓝色的惊叹号。 |
3 | console.error([data][, ...]) 输出错误消息的。控制台在出现错误时会显示是红色的叉子。 |
4 | console.warn([data][, ...]) 输出警告消息。控制台出现有黄色的惊叹号。 |
5 | console.dir(obj[, options]) 用来对一个对象进行检查(inspect),并以易于阅读和打印的格式显示。 |
6 | console.time(label) 输出时间,表示计时开始。 |
7 | console.timeEnd(label) 结束时间,表示计时结束。 |
8 | console.trace(message[, ...]) 当前执行的代码在堆栈中的调用路径,这个测试函数运行很有帮助,只要给想测试的函数里面加入 console.trace 就行了。 |
9 | console.assert(value[, message][, ...]) 用于判断某个表达式或变量是否为真,接收两个参数,第一个参数是表达式,第二个参数是字符串。只有当第一个参数为false,才会输出第二个参数,否则不会有任何结果。 |
process:
这是一个全局变量,即为global的属性
它用于描述当前Node.js 进程状态的对象,提供了一个与操作系统的简单接口。通常在你写本地命令行程序的时候,少不了要 和它打交道。下面将会介绍 process 对象的一些最常用的成员方法。
说白了就是写命令行交互程序必须的东西,详细看菜鸟教程吧:Node.js 全局对象 | 菜鸟教程
node.js常用工具
util用于弥补JavaScript核心功能的不足,
util.callbackify(original)先搁置,因为自己对于异步错误补偿等方面不是很清楚。
util.inherits
可以用于继承,因为JavaScript的继承是基于原型复制的,利用这个函数可以方便的进行继承。
demo:
var util = require('util');
function Base() {
this.name = 'base';
this.base = 1991;
this.sayHello = function() {
console.log('Hello ' + this.name);
};
}
Base.prototype.showName = function() {
console.log(this.name);
};
function Sub() {
this.name = 'sub';
}
util.inherits(Sub, Base);
var objBase = new Base();
objBase.showName();
objBase.sayHello();
console.log(objBase);
var objSub = new Sub();
objSub.showName();
//objSub.sayHello();
console.log(objSub);
base Hello base { name: 'base', base: 1991, sayHello: [Function] } sub { name: 'sub' }
util.inspect
用于将任何对象转换为字符串的方法
util.inspect(object,[showHidden],[depth],[colors]) 它至少接受一个参数 object,即要转换的对象。
第二个参数如果给true的话会显示更多的隐藏信息
depth 表示最大递归的层数,如果对象很复杂,你可以指定层数以控制输出信息的多 少。如果不指定depth,默认会递归 2 层,指定为 null 表示将不限递归层数完整遍历对象。 如果 colors 值为 true,输出格式将会以 ANSI 颜色编码,通常用于在终端显示更漂亮 的效果。
var util = require('util');
function Person() {
this.name = 'byvoid';
this.toString = function() {
return this.name;
};
}
var obj = new Person();
console.log(util.inspect(obj));
console.log(util.inspect(obj, true));
结果:
Person { name: 'byvoid', toString: [Function] } Person { name: 'byvoid', toString: { [Function] [length]: 0, [name]: '', [arguments]: null, [caller]: null, [prototype]: { [constructor]: [Circular] } } }
util.isArray()
用于判断给定参数是否为数组
util.isDate()
用于判断给定参数是否为一个日期
node.js的文件系统
Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API。 Node 导入文件系统模块(fs)语法如下所示:
var fs = require("fs")
异步和同步:
Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。
异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。
建议使用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。
demo:
var fs = require("fs");
// 异步读取
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("异步读取: " + data.toString());
});
// 同步读取
var data = fs.readFileSync('input.txt');
console.log("同步读取: " + data.toString());
console.log("程序执行完毕。");
node file.js 同步读取: 菜鸟教程官网地址:www.runoob.com 文件读取实例 程序执行完毕。 异步读取: 菜鸟教程官网地址:www.runoob.com 文件读取实例
打开文件
fs.open(path, flags[, mode], callback)
参数使用说明如下:
-
path - 文件的路径。
-
flags - 文件打开的行为。具体值详见下文。
-
mode - 设置文件模式(权限),文件创建默认权限为 0666(可读,可写)。
-
callback - 回调函数,带有两个参数如:callback(err, fd)。
var fs = require("fs");
console.log("begin");
fs.open("input.txt",function(err){
if(err){
console.log(err);
}
console.log("finish");
})
获取文件信息
fs.stat(path, callback)
参数使用说明如下:
-
path - 文件路径。
-
callback - 回调函数,带有两个参数如:(err, stats), stats 是 fs.Stats 对象。
var fs = require("fs");
console.log("准备打开文件!");
fs.stat('input.txt', function (err, stats) {
if (err) {
return console.error(err);
}
console.log(stats);
console.log("读取文件信息成功!");
// 检测文件类型
console.log("是否为文件(isFile) ? " + stats.isFile());
console.log("是否为目录(isDirectory) ? " + stats.isDirectory());
});
node file.js 准备打开文件! { dev: 16777220, mode: 33188, nlink: 1, uid: 501, gid: 20, rdev: 0, blksize: 4096, ino: 40333161, size: 61, blocks: 8, atime: Mon Sep 07 2015 17:43:55 GMT+0800 (CST), mtime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST), ctime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST) } 读取文件信息成功! 是否为文件(isFile) ? true 是否为目录(isDirectory) ? false
写入文件
fs.writeFile(file, data[, options], callback)
默认的打开模式是w,会覆盖掉现有的文件!!!
参数使用说明如下:
-
file - 文件名或文件描述符。
-
data - 要写入文件的数据,可以是 String(字符串) 或 Buffer(缓冲) 对象。
-
options - 该参数是一个对象,包含 {encoding, mode, flag}。默认编码为 utf8, 模式为 0666 , flag 为 'w'
-
callback - 回调函数,回调函数只包含错误信息参数(err),在写入失败时返回。
var fs = require("fs");
console.log("begin");
var data = "write test"
fs.writeFile("test.txt",data,function(err){
if (err){
return console.log(err);
}
console.log("success");
fs.readFile("test.txt",function(err,data){
console.log("读取出来的数据:"+data.toString());
});
});
读取文件
fs.read(fd, buffer, offset, length, position, callback)
参数使用说明如下:
-
fd - 通过 fs.open() 方法返回的文件描述符。
-
buffer - 数据写入的缓冲区。
-
offset - 缓冲区写入的写入偏移量。
-
length - 要从文件中读取的字节数。
-
position - 文件读取的起始位置,如果 position 的值为 null,则会从当前文件指针的位置读取。
-
callback - 回调函数,有三个参数err, bytesRead, buffer,err 为错误信息, bytesRead 表示读取的字节数,buffer 为缓冲区对象
demo:
var fs = require("fs");
console.log("begin");
var buf = new Buffer.alloc(1024);//分配缓冲区内存
fs.open("input.txt","r+",function(err,fd){
console.log("open success")
fs.read(fd,buf,0,buf.length,0,function(err,bytes){
console.log(bytes+'字节被读取');
if(bytes>0){
console.log(buf.slice(0,bytes).toString());
}
});
});
该方法个人认为过于复杂,不如用readfile
关闭文件
fs.close(fd, callback)
参数使用说明如下:
-
fd - 通过 fs.open() 方法返回的文件描述符。
-
callback - 回调函数,没有参数。
var fs = require("fs");
var buf = new Buffer.alloc(1024);
console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("准备读取文件!");
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("文件关闭成功");
});
});
});
node file.js 准备打开文件! 文件打开成功! 准备读取文件! 菜鸟教程官网地址:www.runoob.com 文件关闭成功
删除文件
fs.unlink(path, callback)
参数使用说明如下:
-
path - 文件路径。
-
callback - 回调函数,没有参数。
var fs = require("fs");
console.log("准备删除文件!");
fs.unlink('input.txt', function(err) {
if (err) {
return console.error(err);
}
console.log("文件删除成功!");
});
创建目录
fs.mkdir(path[, options], callback)
参数使用说明如下:
-
path - 文件路径。
-
options 参数可以是:
- recursive - 是否以递归的方式创建目录,默认为 false。
- mode - 设置目录权限,默认为 0777。
-
callback - 回调函数,没有参数。
var fs = require("fs");
// tmp 目录必须存在
console.log("创建目录 /tmp/test/");
fs.mkdir("/tmp/test/",function(err){
if (err) {
return console.error(err);
}
console.log("目录创建成功。");
});
读取目录
fs.readdir(path, callback)
参数使用说明如下:
-
path - 文件路径。
-
callback - 回调函数,回调函数带有两个参数err, files,err 为错误信息,files 为 目录下的文件数组列表。
var fs = require("fs");
console.log("查看 /tmp 目录");
fs.readdir("/tmp/",function(err, files){
if (err) {
return console.error(err);
}
files.forEach( function (file){
console.log( file );
});
});
node file.js 查看 /tmp 目录 input.out output.out test test.txt
删除目录
fs.rmdir(path, callback)
参数使用说明如下:
-
path - 文件路径。
-
callback - 回调函数,没有参数。
var fs = require("fs");
// 执行前创建一个空的 /tmp/test 目录
console.log("准备删除目录 /tmp/test");
fs.rmdir("/tmp/test",function(err){
if (err) {
return console.error(err);
}
console.log("读取 /tmp 目录");
fs.readdir("/tmp/",function(err, files){
if (err) {
return console.error(err);
}
files.forEach( function (file){
console.log( file );
});
});
更多补充:https://www.runoob.com/nodejs/nodejs-fs.html
node.js post/get
get:
var http = require("http");
var url = require("url");
http.createServer(function(req,res){
res.writeHead(200,{'Content-Type':'text/plain'});
var params = url.parse(req.url,true).query;
res.write("name:"+params.name);
res.write("url:"+params.url);
res.end();
}).listen(3000);
利用url模块来解析url的数据,.query可以获得键值对形式的get数据
post:
var http = require("http");
var querystring = require("querystring");
var postHTML =
'<html><head><meta charset="utf-8"></head>' +
'<body>' +
'<form method="post">' +
'网站名: <input name="name"><br>' +
'网站 URL: <input name="url"><br>' +
'<input type="submit">' +
'</form>' +
'</body></html>';
http.createServer(function(req,res){
var body = '';
req.on("data",function(chunk){
body += chunk;
});
req.on("end",function(){
body = querystring.parse(body);
res.setHeader('Content-Type', 'text/html; charset=utf-8')
if(body.name && body.url){
res.write("name:" + body.name);
res.write("<br>" );
res.write("url:" + body.url);
}
else{
res.write(postHTML);
}
res.end();
})
}).listen(3000);
这里有一个大坑是如果content-type里面设置的是text/plain则不会解析html标签。
工具模块
node.js web模块
-
Client - 客户端,一般指浏览器,浏览器可以通过 HTTP 协议向服务器请求数据。
-
Server - 服务端,一般指 Web 服务器,可以接收客户端请求,并向客户端发送响应数据。
-
Business - 业务层, 通过 Web 服务器处理应用程序,如与数据库交互,逻辑运算,调用外部程序等。
-
Data - 数据层,一般由数据库组成。
偷懒,,,详细:Node.js Web 模块 | 菜鸟教程