Node.js的简介及优缺点

Node与Chrome

Node除了HTML、WebKit和显卡相关技术没有支持外Node的结构与Chrome十分相似,如果你想学习node 不得不了解的就是chrome的v8在这里插入图片描述

Node的特点

  • Node最大的特点就是异步I/O,以读取文件为例,这里的“发起读取文件”是在”读取文件完成“之前输出的。同样”读取文件完成“的执行也取决于读取文件的异步调用何时结束。
var fs = require('fs')
fs.readFile('path', function(err, file) {
    
    
	console.log('读取文件完成')
})
console.log('发起读取文件')
  • 事件与回调函数
    • 事件的编程方式具有轻量级、松耦合、只关注事物等优势,但是在多个异步任务的场景下,事件与事件之间各自独立如何协作是个问题。
  • 单线程
    • 单线程的好处是不用像多线程编程那样处处在意状态的同步问题,这里没有死锁的存在,也没有线程上下文交换所带来的性能上的开销,但是单线程无法利用多核CPU,并且错误会引起整个应用的退出,应用的健壮性值得考验,大量计算占用CPU导致无法继续调用异步I/O,在Node中,长时间的CPU占用也会导致后续的异步I/O发不出调用,已完成的异步I/O的回调函数也会得不到及时的执行。
    • Node采用了与Web Workers相同的思路来解决单线程中大量计算的问题:Child_process。子进程的出现,意味着Node可以从容的应对单线程在健壮性和无法利用多核CPU的问题。通过计算分发到各个子进程,可以将大量的计算分解掉,然后通过进程之间的事件消息来传递结果,这可以很好的保持应用模型的简单和低依赖。
  • 跨平台
    • Node兼容Windows和*nix平台,它在操作系统与Node上层模块之间构建了一层平台层架构,即libuv。

Node的应用场景

  • I/O密集型

    • Node最强悍的地方就在于处理异步I/O,I/O密集的又是主要在于Node利用事件循环的处理能力,而不是启动每一个线程为每一个请求服务,资源占用极少。
  • 是否不擅长CPU密集型业务

    • Node优秀的运算能力主要来自V8的深度性能优化。
      CPU密集型应用给Node带来的挑战:
      由于JavaScript单线程的原因,如果长时间运行的计算(如大循环),将导致CPU时间片不能释放,使得后续I/O无法发起。但是适当调整和分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起,这样既可以同时受到并行异步I/O的好处,又能充分利用CPU。
      Node充分利用CPU的方式:
      通过编写C/C++扩展的方式高效的利用CPU,将一些V8不能做到性能极致的地方通过C/C++来实现;
      通过子进程的方式,利用进程间的消息传递结果,将计算和I/O分离;
      CPU密集不可怕,如何合理调度是诀窍。
  • 分布式应用

    • 利用Node做Node中间层。

异步编程

函数式编程

  • 在javascript中,函数作为一等公民,使用上非常自由,无论调用它,或者作为参数,或者作为返回值均可。函数的灵活性是js比较吸引人的地方之。

高阶函数:

  • 在通常的语言中,函数的参数只接受基本的数据类型或者对象引用,返回值也只是基本数据类型和对象引用。
  • 高阶函数可以把函数作为参数,或是将函数作为返回值的函数。

偏函数用法:

  • 偏函数用法是指创建一个调用另一个部分——参数或变量已经预置的函数——的函数的用法:
var toString = Object.prototype.toString;
var isString = (obj) => {
    
    
	return toString.call(obj) == '[object String]';
}
var isFunction = (obj) => {
    
    
	return toString.call(obj) == '[object Function]';
}
===================================================
var isType = (type) => {
    
    
	return (obj) => {
    
    
		return toString.call(obj) == '[object ' + type + ']';
	}
}

var isString = isType('String')
var isFunction = isType('Function')

异步编程的优势与难点

优势:

  • Node最大的优势莫过于基于事件驱动的非阻塞I/O模型,这是它的灵魂所在。非阻塞的异步I/O可以使CPU与I/O互相不依赖等待,让资源得到更好的利用。对于网络应用而言,并行带来的想象空间更大,延展而开的是分布式和云。
  • 由于时间云荒墨影需要应对海量请求,海量请求同时作用在单线程上,就需要防止任何一个计算耗费过多的CPU时间片。至于是计算密集型还是I/O密集型,只要计算不影响异步I/O的调度,那就不构成问题。建议对CPU的耗用不超过10ms,或者将大量的计算分解为小量计算,通过setImmediate()进行调度,只要合理的利用Node的异步模型与V8的高性能,就可以充分发挥CPU和I/O资源的优势。

难点:

  • 异常处理:过去我们处理异常时,通常使用类Java的try/catch/final语句块进行异常捕获。但是这对于异步编程并不一定试用。
  • 函数嵌套过深:在前端开发中DOM事件相对而言不会存在相互依赖或者需要多个事件协作的场景,但是在Node中经常会存在多个异步调用相互依赖的关系。
  • 阻塞代码:javascript没有sleep()这样的线程沉睡功能,当我们需要延迟执行的时候一般都会用到settimeout或者setinterval,但是这段代码会持续的占用CPU进行判断。
  • 多线程编程:javascript通常谈的是在单一线程上执行代码,但是在Node中,如果服务器是多核CPU,单个Node进程实质上没有充分利用多核CPU的。
  • 异步转同步:目前Node中试图同步式编程,但并不能得到原生的支持,需要接触库或者编译等手段来实现。

异步编程解决方案

  • 事件发布/订阅模式
  • Promise/Deferred模式
  • 流程控制库
  • 生成器Generators/ yield
  • async/await (目前为止最为常用)

猜你喜欢

转载自blog.csdn.net/shadowfall/article/details/118531095