首页 > 代码库 > 深入浅出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. 每个异步调用结束时,从队列中取出新的异步调用执行