首页 > 代码库 > 深入浅出NodeJS——异步编程
深入浅出NodeJS——异步编程
函数式编程
Javascript中函数作为一等公民,函数看成普通对象,可以作为参数或者返回值。
高阶函数:函数作为参数或者将函数作为返回值的函数
异步编程优势
基于事件驱动的非阻塞I/O模型
异步编程难点
(1) 异常处理,通常try/catch不一定适用,因为callback并不是在当前Tick中执行。
Node在异常处理中约定将异常作为回调函数的第一个实参传回。
(2) 函数嵌套过深
(3) 代码阻塞:没有sleep函数,通过setInterval()和setTimeout()模拟
(4) 多线程编程
(5) 异步转同步
异步编程解决方案
(1) 事件发布、订阅模式
Node自身提供events模块,是发布/订阅模式的简单实现,部分模块继承自它,不同于DOM的事件模型不存在冒泡。
addLinstener/on/once 注册事件
removeListener/removeAllListeners 删除事件
emit() 触发事件
事件发布/订阅模式自身并无同步和异步调用的问题,在Node中,emit()调用多半是伴随事件循环而异步触发。
a. 默认Node中若对一个事件添加超过了10个侦听器,将会得到一个警告
b. 为了处理异常,EventEmittter对象将error对象进行特殊处理,若触发了error事件,EventEmittter会检查是否有error事件监听过监听器,若添加了则错误会交给监听器处理,若外部没有捕获异常,将会引起线程退出。
(2) Promise/Deferred模式
使用事件的方式,执行流程需要被预先设定,即便是分支也需要预先设定,这是由发布/订阅机运行制决定的。
先执行异步调用,延迟传递处理方式,Promise/Deferred模式。
在原始API中,一个事件智能处理一个回调,通过Deferred对象可以对事件加入任意的业务处理逻辑。
(3) 流程控制库
(1) 尾触发与Next
尾触发:需要手工调用才能持续执行后续调用的方法,如connect模块中的next方法
(2) async
https://github.com/caolan/async
异步的串行执行:async.series([fn], fn)
异步的并行执行:async.parallel([fn], fn)
异步调用的依赖处理:async.waterfall
自动依赖处理:async.auto
(3) Step
比async更轻量,只提供一个接口Step,Step(task1,task2,task3)
(4) wind
异步并发控制
异步I/O非常容易实现并发访问,但是底层操作系统并发处理能力也是有限制的,因此需要对并发进行控制。
bagpipe的解决方案
a. 通过一个队列来控制并发量
b. 若当前活跃的异步调用小于限定值,则从队列中取出
c. 若活跃调用达到限定值,调用暂时存放在队列中
d. 每个异步调用结束时,从队列中取出新的异步调用执行