NodeJs 深入浅出之旅:异步 I/O (下)🐂
Promise/Deferred 模式 🎱
使用事件的方式是,执行流程需要被预先设定,即使是分支,也需要预先设定,这是由发布/订阅模式的运行机制所决定的。
但是在 Promise/Deferred 模式中,采用先执行异步调用,延迟传递处理的方式
promise/deferred 模式是,根据 promise/A 或者它的增强修改版 promise/A+ 规范 实现的 promise 异步操作的一种实现方式。
在原始的 API 中,一个事件只能处理一个回调。而通过 Deferred 对象,可以对事件加入任意的业务处理逻辑。
比如:
该模式包括两个部分: promise 和 deferred
Promise ⚽
Promise 对象有以下两个特点(下面这两点也是官方最精华的总结):
(1)对象的状态不受外界影响。Promise
对象代表一个异步操作,有三种状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise
这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise
对象的状态改变,只有两种可能:从pending
变为fulfilled
和从pending
变为rejected
。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved
(已定型)。如果改变已经发生了,你再对Promise
对象添加回调函数,也会立即得到这个结果。这与事件(Event
)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
阮一峰老师的 Promise: https://www.bookstack.cn/read/es6/docs-promise.md
模拟 Promise ⚾
对于 Promise 对象,只要具备then()
方法即可。
对then()
方法的要求:
接受完成态、错误态的回调方法,在操作完成或者出现错误时,调用对应方法
可选地支持 progress 事件回调作为第三个方法
then()
方法只接受 function 对象,其他对象将被忽略then()
方法继续返回 Promise 对象,以实现链式调用then()
方法定义:then(fulfilledHandler, errorHandler, progressHandler)
例子:
此时的DeferredMade
类就类似于promise
,在调用时可以放在一个函数中模拟使用:
从这里的代码上,可以看到Promise
和Deferred
的差别:
Deferred
主要是作用于内部,用于维护异步模型的状态Promise
主要作用于外部,通过then()
方法暴露给外部添加自定义逻辑
Promise
和Deferred
的关系:
适用情况 🏀
与发布/订阅模式相比,Promise/Deferred 模式的接口和模型都非常简洁。
将业务中不可变的部分封装在了 Deferred,可变部分交给了 Promise。
对于不同的场景,都需要去封装和改造其 Deferred。
如果场景不常用,封装花费的事件与带来的效率相比并不划算。
Promise 是高级接口,一旦定义,不太容易变化,但对典型问题解决非常有效
事件是低级接口,可以构成更多复杂的场景
流程控制库 🏈
在 express 当中,还有一类需要手工调用才能持续执行后续调用的方式,这类方法叫做尾触发,常见的是 next。
在 express 中,就会有 next 在编写中间件时较为常用。
参考:https://www.jianshu.com/p/6322c32001b7
总结 🎳
在 Node 异步处理过程中,最常使用的就是事件发布订阅和 Promise 了,当然流程控制库的方式也会用大。 对于不同的场景,需要采取最使用的方法,这一点就需要依靠自身判断了,毕竟谁也不知道后续会不会加需求 (真的对后期需求变更是深恶痛绝)
版权声明: 本文为 InfoQ 作者【空城机】的原创文章。
原文链接:【http://xie.infoq.cn/article/9b8188ad21e66079b6add8cf6】。文章转载请联系作者。
评论