您的位置:首页 > Web前端 > Node.js

Node.js API快速入门

2018-11-01 16:55 711 查看

Node.js API 快速入门

一、事件EventEmitter

const EventEmitter = require('events');
class MyEmitter extends EventEmitter{}
const eventEmitter = new MyEmitter();
//设置链接事件监听器
eventEmitter.on('connection', (url) => {
console.log(`链接 ${url} 成功!`);
eventEmitter.emit('data_received', '神秘代码');
});
//数据接收监听器
eventEmitter.on('data_received', (data) => {
console.log(`数据 ${data} 接收成功!`);
});
//触发链接事件
eventEmitter.emit('connection', 'Google');
console.log('任务完成!');
/*链接 Google 成功!
据 神秘代码 接收成功!
任务完成!*/

二、二进制缓存Buffer

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。

但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,

定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。

原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,

但它对应于 V8 堆内存之外的一块原始内存。

//创建一个长度为512,且用0填充的Buffer
let buf = Buffer.alloc(512);
//缓冲区长度
console.log(buf.length); //512
//向缓冲区写入字符串,默认使用utf-8编码
//返回实际写入的大小,如果缓存区空间不足,只会写入一部分
let len = buf.write('写入了一些东西');
console.log(`写入字节数: ${len}`); //21
//从缓存区读取数据
console.log(buf.toString('base64', 0, 12)); //5YaZ5YWl5LqG5LiA

三、流Stream

Stream 是一个抽象接口,Node.js,Stream 有四种流类型:

  • Readable - 可读操作

  • Writable - 可写操作

  • Duplex - 可读可写操作

  • Transform - 操作被写入数据,然后读出结果

所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有:

  • data - 当有数据可读时触发。

  • end - 没有更多的数据可读时触发。

  • error - 在接收和写入过程中发生错误时触发。

  • finish - 所有数据已被写入到底层系统时触发。

读取和写入:

const fs = require('fs');
let data = '';
let inputData = 'What\'s the matter with you. Say me something new.';
//创建可读流
let readerStream = fs.createReadStream('sth.txt');
readerStream.setEncoding('UTF8');
//处理流事件
readerStream.on('data', (buf) => {
data += buf;
});
readerStream.on('end', () => {
console.log(data);
});
readerStream.on('error', (err) => {
console.log(err.stack);
});
console.log('读出完毕??????');
/*
程序执行完毕!
I have a orange.*/

let writerStream = fs.createWriteStream('output.txt');
writerStream.write(data, 'UTF8');
//标记文件末尾
writerStream.end();
//处理流事件
writerStream.on('finish', () => {
console.log('写入完成!');
});
writerStream.on('error', (err) => {
console.log(err.stack);
});
console.log('写入完毕?????');

/*
读出完毕??????
写入完毕?????
写入完成!
I have a orange.*/

管道流:

管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传递到另外一个流中。

const fs = require('fs');
let reader = fs.createReadStream('sth.txt');
//如果没有input.txt会创建
let writer = fs.createWriteStream('input.txt');
//读取sth.txt的内容写入到input.txt中去
reader.pipe(writer);

链式流:

链式是通过连接输出流到另外一个流并创建多个流操作链的机制。链式流一般用于管道操作。

接下来我们就是用管道和链式来压缩和解压文件。创建 compress.js 文件, 代码如下:

const fs = require('fs');
const zlib = require('zlib');

//压缩文件
fs.createReadStream('input.txt')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('input.txt.gz'));
console.log('文件压缩完成');

// 解压 input.txt.gz 文件为 input.txt
fs.createReadStream('input.txt.gz')
.pipe(zlib.createGunzip())
.pipe(fs.createWriteStream('input.txt'));
console.log("文件解压完成。");

四、全局对象

在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,

所有全局变量(除了 global 本身以外)都是 global 对象的属性。

具体API略

五、文件系统---fs模块

Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 

和同步的 fs.readFileSync()。异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。

建议大家使用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。

const fs = require('fs');
console.log('准备写入文件:');
fs.open()
//对同一文件多次使用 fs.writeFile 且不等待回调,是不安全的。
//对于这种情况,建议使用 fs.createWriteStream。
//如果 file 是一个文件描述符,则它不会被自动关闭。
fs.writeFile('input.txt', '被写入文件的内容,可以是string或者是Buffer', (err) => {
//如果有错误
if (err) {
return console.error(err);
}
console.log('数据写入成功');
console.log('准备读取文件');
//fs.readFile() 函数会缓存整个文件。 为了最小化内存占用,
// 尽可能优先使用 fs.createReadStream()。
//如果 path 是一个文件描述符,则它不会被自动关闭。
fs.readFile('input.txt', (err, data) => {
if (err) {
return console.error(err);
}
console.log('读取到的数据是:' + data);
})
});

六、Web模块

Node.js 提供了 http 模块,http 模块主要用于搭建 HTTP 服务端和客户端。

获取get内容:

const http = require('http');
const url = require('url');

http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
//解析url参数,获取get中的内容
let params = url.parse(req.url, true).query;
res.write(`Name: ${params.name} \n`);
res.write(`Phone: ${params.phone}`);
res.end();
}).listen(3000);
//浏览器输入:http://localhost:3000/?name=tang&phone=898989
//浏览器显示:
// Name: tang
//Phone: 898989

获取post内容:

var http = require('http');
var querystring = require('querystring');
http.createServer(function(req, res){
// 定义了一个post变量,用于暂存请求体的信息
var post = '';
// 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
req.on('data', function(chunk){
post += chunk;
});
// 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
req.on('end', function(){
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(3000);

创建web服务器:

const http = require('http');
const url = require('url');
const fs = require('fs');

function controller(req, res) {
//解析文件名
let pathName = url.parse(req.url).pathname;
//输出请求的文件名
console.log('请求的文件名为:'+ pathName);
//读取请求的html文件内容
fs.readFile(pathName.substring(1), (err, data) => {
if (err) {
console.error(err);
res.writeHead(404, {'Content-Type' : 'text/html'});
} else {
res.writeHead(200, {'Content-Type' : 'text/html'});
//响应文件内容
res.write(data.toString());
}
res.end();
});
}
http.createServer(controller).listen(8099);
console.log('Server running at http://localhost:8099/');

七、Express框架

GET方法:

const express = require('express');
const app = express();

app.use(express.static('public'));
app.get('/', (req, res) => {
res.sendFile( __dirname + '/' + 'home.html');
});
app.get('/dataBack', (req, res) => {
let dataBackJSON = {
"FirstName: " : req.query.firstName,
"LastName: " : req.query.lastName
};
console.log(dataBackJSON);
res.send(JSON.stringify(dataBackJSON));
});
app.listen(8099, () => {
console.log('Listening');
});

POST方法:

const express = require('express');
const app = express();
const bodyParser = require('body-parser');

app.use(express.static('public'));

let urlencodedParser = bodyParser.urlencoded({ extended: false });
app.get('/home', (req, res) => {
res.sendFile(`${__dirname}/home.html`);
});
app.post('/dataBack', urlencodedParser, (req, res) => {
let data = {
"FirstName: " : req.body.firstName,
"LastName: " : req.body.lastName
};
console.log(data);
res.send(JSON.stringify(data));
});

app.listen(8099, () => {
console.log('Just do it!');
});

文件上传:

const express = require('express');
const app = express();
const fs = require('fs');
const bodyParser = require('body-parser');
const multer  = require('multer');

app.use(express.static('public'));
app.use(multer({ dest: '/tmp/'}).array('image'));

app.get('/home', (req, res) =>{
res.sendFile( __dirname + "/" + "home.html" );
});

app.post('/upload', (req, res) => {
let uploadFile = req.files[0];
console.log(uploadFile);//上传文件的信息
let desFile = __dirname + '/' + uploadFile.originalname;
fs.readFile(uploadFile.path, (err, data) => {
if (err) return console.error(err);
fs.writeFile(desFile, data, (err) => {
if (err) return console.error(err);
let result = {
"message: " : 'Upload Success!',
"FileName: " : uploadFile.originalname
};
console.log(result);
res.end(JSON.stringify(result));
});
});
});

app.listen(8099, () => {
console.log(`Listening`);
});

八、 多进程

1.child_process.exec(command[, options], callback)

使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回。

参数:

command: 字符串,将要运行的命令,参数使用空格隔开。

options: 对象,可以是:

    cwd ,字符串,子进程的当前工作目录

    env,对象 环境变量键值对

    encoding ,字符串,字符编码(默认: 'utf8')

    shell ,字符串,将要执行命令的 Shell(默认: 在 UNIX 中为

/bin/sh
, 在 Windows 中为
cmd.exe
, Shell 应当能识别 
-c
开关在 UNIX 中,或 
/s         /c
 在 Windows 中。 在Windows 中,命令行解析应当能兼容
cmd.exe

    timeout,数字,超时时间(默认: 0)

    maxBuffer,数字, 在 stdout 或 stderr 中允许存在的最大缓冲(二进制),如果超出那么子进程将会被杀死 (默认: 200*1024)

    killSignal ,字符串,结束信号(默认:'SIGTERM')

    uid,数字,设置用户进程的 ID

    gid,数字,设置进程组的 ID

callback回调函数,包含三个参数error, stdout 和 stderr。

该方法方法返回最大的缓冲区,并等待进程结束,一次性返回缓冲区的内容。

const cps = require('child_process');

for (let i = 0; i < 3; i++) {
let wps = cps.exec('node support.js ' + i, (err, stdout, stderr) => {
if (err) console.log(err.stack);
console.log(`standOut: ${stdout}`);
});
wps.on('exit', (code) => {
console.log('子进程已经退出,退出码为:' + code);
});
}
/*子进程已经退出,退出码为:0
standOut: 进程 0 执行

子进程已经退出,退出码为:0
standOut: 进程 1 执行

子进程已经退出,退出码为:0
standOut: 进程 2 执行*/
console.log(`进程 ${process.argv[2]} 执行`);

2.child_process.spawn(command[, args][, options])

使用指定的命令行参数创建新进程,spawn() 方法返回流 (stdout & stderr),在进程返回大量数据时使用。

进程一旦开始执行时 spawn() 就开始接收响应。

const cps = require('child_process');

for (let i = 0; i < 3; i++) {
let wps = cps.spawn('node', ['support.js', i]);
wps.stdout.on('data', (data) => {
console.log('stdout: ' + data);
});
wps.stderr.on('data', (data) => {
console.log(`stdout: ${data}`);
});
wps.on('close', (code) => {
console.log(`子进程${i}已退出,退出码:${code}`);
});
}
/*stdout: 进程 0 执行

子进程0已退出,退出码:0
stdout: 进程 1 执行

stdout: 进程 2 执行

子进程1已退出,退出码:0
子进程2已退出,退出码:0*/

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: