目录
一.node的特点
1.基于V8引擎(webkit内核)渲染和解析JS(类似的还有webview和谷歌浏览器等),它不是后台语言,它是一个工具或环境,用来解析js的工具或者环境。我们一般会把node安装在服务器上,在服务器上写一些js代码,实现服务端的一些功能。基于命令node xxx.js把js代码运行在node环境下
2. 单线程异步非阻塞的I/O操作
JS在客户端浏览器中运行,是否可以对客户端本地的文件进行读写操作?
不能,要保证客户端的信息安全。input:type="file" 文件上传表单除外,但这种也需要用户手动进行选择才可以。
JS在服务器运行能否对服务端的文件进行操作?
可以,node赋予js进行I/O读写的能力(内置模块FS)
3.window 和 global
1)在客户端浏览器中运行的js,js的全局对象是window,它提供了很多内置的属性和方法
2)在node中运行js,js全局对象是global, 也包括许多内置的属性
1.proceess:node中做进程管理的属性,常用有
- process.nextTick()
- process.env
2.Buffer:数据格式管理的;
3.setImmediate 立刻执行(类似于setTimeout(fun,0))
注意:在REPL命令中输出this是global,但在xxx.js中输出的this是当前模块本身。
4.不适合处理CPU密集型的任务
nodejs是单线程的,如果遇到涉及到较大计算量的cpu密集型的任务,其后面的代码是不会执行的。但配合异步IO和事件循环是可以处理一些高并发的请求的。
let http = require('http');
function sleepTime (time) {
const sleep = Date.now() + time * 1000;
while(Date.now() < sleep) {}
return;
}
sleepTime(4); // 这就是一个cpu密集型的任务,占用主线程
const server = http.createServer((req,res) => {
res.end('server starting');
});
server.listen(8080,() => {
console.log('start on 8080......');
})
二.node在实际项目中的应用
1)webpack是基于node环境运行的
2)npm是安装了node后自带的模块管理工具,基于它可以安装和卸载对应的模块
3)基于node.js实现服务器的功能操作
项目架构1:基于node.js架构全栈项目(一般用于中小型项目)
项目架构2:基于node.js构建中间层
特点:单线程异步,无阻塞I/O,事件驱动。node.js作为服务层,抗压和抗并发的能力不错
这种方式,可以基于node.js实现跨域访问,客户端和中间层在一个域下(同源),基于中间层从第三方服务器上获取数据(node.js可以跨域获取数据)
另外,当客户端和服务器同时进行开发的时候,需要两端协商接口规范(API文档),然后由服务端先开发出一个伪接口,有时这个伪接口就是基于node.js开发的一套数据mock的后台,在项目联调的时候,再把接口切换到真实的后台上。
项目架构3:基于node.js实现服务器渲染
客户端数据绑定后在源代码中看不到绑定的内容,不利于SEO优化。所以有些产品需要放弃客户端渲染,改为服务器渲染,这个渲染操作就由node处理。
三.node的架构
nodejs的核心是由三层组成。最上层Native modules是内置核心模块,里面暴露了js的内置功能模块接口;中间层Bindings是在使用对应模块时调用对应模块的c++函数的,且需要V8引擎配合完成;最下层包括许多模块,其中V8引擎用于构建js代码的运行环境,负责js代码的执行,js和底层c++代码的转换;libuv库用于处理node的事件循环,事件队列,异步IO;除此之外还有其他若干模块对应不同的功能。
node中如何实现异步IO?
对于IO分为阻塞和非阻塞两种类型,对于非阻塞的IO,CPU的时间片可以处理其他的事务,从而提升性能,但立即返回的不是最终需要的数据,而是调用的状态,操作系统为了得到最终的数据,会使用轮询让应用程序重复调用IO操作,从而确认IO操作是否已经完成,一旦完成就将最终的数据返回,但此时程序依旧等待IO的结果,依旧是阻塞的。在node中使用libuv库,在IO操作调用发起后直接进行下一个操作的处理,等待IO的结果处理完后,通知js主线程通过回调的方式将结果传递给当前代码。 nodejs单线程配合事件驱动架构及libuv实现异步IO。
node事件驱动架构?
类似消息订阅发布模式,发布者广播消息,订阅者接受消息。
当libuv库接收到了异步IO操作时,事件多路分解器找到当前平台环境下可用的IO处理接口,等待IO操作结束后通过对应的事件添加到事件队列中,随后按照顺序从事件队列中取出事件交给主线程执行。在接收到IO操作时,会发布某个事件,事件的订阅者在IO操作结果返回后执行在订阅时的处理程序,获取结果。
node事件驱动简单代码实现:
let eventEmitter = require('events');
const myEvent = new eventEmitter();
// 绑定事件event1,订阅者
myEvent.on('event1',() => {
console.log('event1执行了');
});
// 触发事件event1,发布者
myEvent.emit('event');
四.node全局对象及全局变量
node中提供关键字global表示全局对象,其上挂载了许多属性和方法。
node中this和global的关系
在node中默认this是空对象,直接判断this和global的关系两者不相等,但在自调用函数中判断两者是相等的。因为在node中每一个文件都是一个独立的模块,每一个模块在执行的时候最外层都被包裹了一个自调用的函数,node会为该函数传递一些固定的参数,例如:__filename,require,__dirname,exports等,包括this;
console.log(this); // {}
console.log(this === global); // false
(function () {
console.log(this === global); // true
})()
1.全局变量process
作用:获取当前正在执行脚本的信息,对当前进程进行一些操作等
1)process.memoryUsage():查看当前脚本内存使用信息
console.log(process.memoryUsage());
输出对象如下:
2)process.cpuUsage():获取当前cpu的信息
console.log(process.cpuUsage());
获取的是用户和操作系统占用的当前CPU的时间片段