Node.js的学习

Node.js是什么


原生js是不能脱离浏览器运行的,而Node.js就能够让js脱离浏览器运行在服务器上。

简而言之,Node.js就是运行在服务端的JavaScript

Node是V8引擎的容器,Node.js是基于Google的V8引擎的。

nodejs是用C++开发的一种运行于服务器端的语言,node的底层是C++,是可以直接运行在电脑上的。

Node.js的作用

  • 编译js代码
  • 读、写电脑上的文件
  • 连接数据库
  • 充当Web服务器
    js代码经过nodejs在电脑上运行的流程

回调函数


Node.js 异步编程的直接体现就是回调。异步编程依托于回调来实现,但不能说使用了回调后程序就异步化。

异步与回调的关系

  1. 关联
    异步任务需要在得到结果时通知JS来读取结果。等待通知的过程就是异步,通知JS读取结果的过程就是回调。

  2. 区别
    异步任务需要用到回调函数来通知结果;
    回调函数却不一定存在于异步任务中,同步任务中也可以用到回调函数。

回调函数就是自己写了却不调用,给别人调用的函数。

EventEmitter


Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。

Node.js 里面的许多对象都会分发事件:一个 net.Server 对象会在每次有新连接时触发一个事件,一个 fs.readStream 对象会在文件被打开的时候触发一个事件。
所有这些产生事件的对象都是 events.EventEmitter 的实例。

EventEmitter 类:
events 模块只提供了一个对象: events.EventEmitter。EventEmitter的核心就是事件触发与事件监听器功能的封装。

EventEmitter 的每个事件由一个事件名和若干个参数组成,事件名是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter 支持若干个事件监听器。

当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。

继承EventEmitter:
大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。

Buffer(缓冲区)


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

Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据。

创建Buffer类Buffer.alloc()_Buffer.from()
写入缓冲区buf.write()
从缓冲区读取数据buf.toString()
将Buffer转换为JSON对象buf.toJSON()
缓冲区合并Buffer.concat()
缓冲区比较buf.compare()
复制缓冲区buf.copy()
剪裁缓冲区buf.slice()
缓冲区长度buf.length

Stream


Stream 是一个抽象接口,Node 中有很多对象实现了这个接口。

四种流类型:

  • Readable - 可读操作。
  • Writable - 可写操作。
  • Duplex - 可读可写操作。
  • Transform - 操作被写入数据,然后读出结果。

常用的事件有:

  • data - 当有数据可读时触发。
  • end - 没有更多的数据可读时触发。
  • error - 在接收和写入过程中发生错误时触发。
  • finish - 所有数据已被写入到底层系统时触发。
var fs = require("fs");
var data = '';
// 创建可读流
var readerStream = fs.createReadStream('input.txt');
// 设置编码为 utf8。
readerStream.setEncoding('UTF8');
// 处理流事件 --> data, end, and error
readerStream.on('data', function(chunk) {
   data += chunk;
});
var fs = require("fs");
var data = '写入文件数据内容';
// 创建一个可以写入的流
var writerStream = fs.createWriteStream('output.txt');
// 使用 utf8 编码写入数据
writerStream.write(data,'UTF8');
// 标记文件末尾
writerStream.end();

管道流

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

var fs = require("fs");
// 创建一个可读流
var readerStream = fs.createReadStream('input.txt');
// 创建一个写入流
var writerStream = fs.createWriteStream('output.txt');
// 管道读写操作
readerStream.pipe(writerStream);

链式流

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

var fs = require("fs");
var zlib = require('zlib');

// 压缩 input.txt 文件为 input.txt.gz
fs.createReadStream('input.txt')
  .pipe(zlib.createGzip())
  .pipe(fs.createWriteStream('input.txt.gz'));
  
// 解压 input.txt.gz 文件为 input.txt
fs.createReadStream('input.txt.gz')
  .pipe(zlib.createGunzip())
  .pipe(fs.createWriteStream('input.txt'));

模块系统


  • 模块是Node.js 应用程序的基本组成部分。
  • 文件和模块是一一对应的,一个 Node.js 文件就是一个模块,这个文件可以是JavaScript 代码、JSON。

Node.js 提供了exports和require两个对象,其中exports是模块公开的接口,require用于从外部获取一个模块的接口,即所获取模块的 exports 对象。

引入当前目录的模块:

var helloWorld= require('./helloWorld');

hello.js 通过 exports 对象把 world 作为模块的访问接口,通过 require(‘./hello’)加载这个模块后,就可以直接访问hello.js 中exports对象的成员函数。

//hello.js
exports.world = () => {
    console.log("hello world!");
    this.saySomething = () =>{
        console.log("hello world222222");
    }
    this.saySomething();
}
//main.js
const hello = require('./hello');
hello.world();

使用module.exports = Hello代替exports.world = function(){},在外部引用该模块时,其接口对象就是要输出的 Hello 对象本身,而不是原先的 exports。

//hello.js
function Hello() { 
    var name; 
    this.setName = function(thyName) { 
        name = thyName; 
    }; 
    this.sayHello = function() { 
        console.log('Hello ' + name); 
    }; 
}; 
module.exports = Hello;
//main.js
var Hello = require('./hello'); 
hello = new Hello(); 
hello.setName('Wocccccc'); 
hello.sayHello(); 

把一个对象封装到模块中:

//hello.js
module.exports = () => {
    console.log("hello world!");
    this.saySomething = "hhhhhhhha";
    this.world = () =>{
        console.log("??????");
    }
}
//main.js
var Hello = require('./hello'); 
hello = new Hello();
console.log(hello.saySomething);
hello.world();

Node.js 中存在 4 类模块(原生模块和3种文件模块):

  • http、fs、path等,原生模块。
  • ./mod或…/mod,相对路径的文件模块。
  • /pathtomodule/mod,绝对路径的文件模块。
  • mod,非原生模块的文件模块。

注:
-exports 和 module.exports 的使用:
如果要对外暴露属性或方法,就用 exports 就行,要暴露对象就用 module.exports;
-若同时使用 exports 和 module.exports:
如果先使用 exports 对外暴露属性或方法,再使用 module.exports 暴露对象,会使得 exports 上暴露的属性或者方法失效。

函数


一个函数可以作为另一个函数的参数。我们可以先定义一个函数,然后传递;

function say(word) {
    console.log(word);
}
function execute(someFunction, value) {
    someFunction(value);
}
execute(say, "Hello");

也可以在传递参数的地方直接定义函数。

//匿名函数
const hello = (say, value)=>{
    say(value);
};
hello((word)=>{console.log(word);}, "hello");

全局对象


Node.js中的全局对象是global,所有全局变量(global自身除外)都是 global对象的属性。

global最根本的作用是作为全局变量的宿主。当你定义一个全局变量时,这个变量同时也会成为全局对象的属性。

最好不要使用var定义变量以避免引入全局变量,因为全局变量会污染命名空间,提高代码的耦合风险。

__filename表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。 如果在模块中,返回的值是模块文件的路径0。
__dirname表示当前执行脚本所在的目录。
setTimeout(function, ms)全局函数在指定的毫秒数后执行函数function。setTimeout()只执行一次指定函数。
clearTimeout(T)全局函数用于停止一个之前通过 setTimeout()创建的定时器 T。
setInterval(function, ms)全局函数在指定的毫秒(ms)数后执行函数function。
clearInterval(T)函数来清除定时器,setInterval()方法会不停地调用函数,直到 clearInterval()被调用或窗口被关闭。
console用于提供控制台标准输出。
process是一个全局变量,即global对象的属性。

  • util.callbackify(original)
  • util.inherits(constructor, superConstructor)
  • util.inspect(object,[showHidden],[depth],[colors])
  • util.isArray(object)
  • util.isRegExp(object)
  • util.isDate(object)

文件系统


Node导入文件系统模块:

var fs = require("fs")

同步异步
Node.js 文件系统模块中的方法均有异步和同步版本。
异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。
异步方法比起同步,异步方法性能更高,速度更快,而且没有阻塞。

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("程序执行完毕。");

异步模式下打开文件:

fs.open(path, flags[, mode], callback)	//callback(err, fd)

异步模式下获取文件信息:

fs.stat(path, callback)	//callback(err, stats), stats 是fs.Stats对象

异步模式下写入文件:

fs.writeFile(file, data[, options], callback)	//options(encoding, mode, flag),callback(err)

异步模式下读取文件:

fs.read(fd, buffer, offset, length, position, callback)	//callback(err, bytesRead, buffer)

异步模式下关闭文件:

fs.close(fd, callback)	//callback没有参数

异步模式下截取文件:

fs.ftruncate(fd, len, callback)	//callback没有参数

删除文件:

fs.unlink(path, callback)	//callback没有参数

创建目录:

fs.mkdir(path[, options], callback)	//options(recursive, mode),callback没有参数

读取目录:

fs.readdir(path, callback)	//callback(err, files)

删除目录:

fs.rmdir(path, callback)	//callback没有参数

常用工具模块


os模块提供了一些基本的系统操作函数
path模块提供了一些用于处理文件路径的小工具
Net模块提供了一些用于底层的网络通信的小工具
DNS模块用于解析域名
Domain简化异步代码的异常处理,可以捕捉处理try catch无法捕捉的异常。

多线程


Node.js 是以单线程的模式运行的;但它使用的是事件驱动来处理并发,我们可以在多核 cpu 的系统上创建多个子进程。

每个子进程总是带有三个流对象:child.stdin, child.stdout 和child.stderr。

Node提供child_process模块来创建子进程:

  1. child_process.exec(command[, options], callback(err, stdout, stderr))
    使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回。exec()方法返回最大的缓冲区,并等待进程结束,一次性返回缓冲区的内容。
  2. child_process.spawn(command[, args][, options])
    使用指定的命令行参数创建新进程。spawn()方法返回流 (stdout & stderr),在进程返回大量数据时使用。进程一旦开始执行时spawn()就开始接收响应。
  3. child_process.fork(modulePath[, args][, options])
    spawn()方法的特殊形式,用于创建进程。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值