node.js(回调函数,事件循环,模块系统,路由,文件系统,post/get请求)

目录

NPM使用

node.js REPL

node.js 回调函数

node.js事件循环

node.js EventEmitter

node.js Buffer(缓冲区)

node.js Steam

node.js模块系统

node.js函数

node.js路由

node.js全局对象

node.js常用工具

node.js的文件系统

node.js post/get

工具模块

node.js web模块


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 Stream(流) | 菜鸟教程


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 对象的方法:

序号方法 & 描述
1console.log([data][, ...])
向标准输出流打印字符并以换行符结束。该方法接收若干 个参数,如果只有一个参数,则输出这个参数的字符串形式。如果有多个参数,则 以类似于C 语言 printf() 命令的格式输出。
2console.info([data][, ...])
该命令的作用是返回信息性消息,这个命令与console.log差别并不大,除了在chrome中只会输出文字外,其余的会显示一个蓝色的惊叹号。
3console.error([data][, ...])
输出错误消息的。控制台在出现错误时会显示是红色的叉子。
4console.warn([data][, ...])
输出警告消息。控制台出现有黄色的惊叹号。
5console.dir(obj[, options])
用来对一个对象进行检查(inspect),并以易于阅读和打印的格式显示。
6console.time(label)
输出时间,表示计时开始。
7console.timeEnd(label)
结束时间,表示计时结束。
8console.trace(message[, ...])
当前执行的代码在堆栈中的调用路径,这个测试函数运行很有帮助,只要给想测试的函数里面加入 console.trace 就行了。
9console.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 工具模块 | 菜鸟教程

 


node.js web模块

  • Client - 客户端,一般指浏览器,浏览器可以通过 HTTP 协议向服务器请求数据。

  • Server - 服务端,一般指 Web 服务器,可以接收客户端请求,并向客户端发送响应数据。

  • Business - 业务层, 通过 Web 服务器处理应用程序,如与数据库交互,逻辑运算,调用外部程序等。

  • Data - 数据层,一般由数据库组成。 

偷懒,,,详细:Node.js Web 模块 | 菜鸟教程 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值