JavaScript:Promise

调表达程序异步和管理并发的两个主要缺陷:缺乏顺序性 和可信任性。

实际上,绝大多数 JavaScript/DOM 平台新增的异步 API 都是基于 Promise 构建的。

什么是Promise

从外部看,由于 Promise 封装了依赖于时间的状态——等待底层值的完成或拒绝,所以 Promise 本身是与时间无关的。因此,Promise 可以按照可预测的方式组成(组合),而不 用关心时序或底层的结果。

反控制反转

回调本身就表达了一种控制反转,所以对回调模式的反转实际就是对反转的反转。 所以反控制反转—-把控制返还给调用代码。

维基百科:关注点分离

关注点分离(Separation of concerns,SOC)是对只与“特定概念、目标”(关注点)相关联的软件组成部分进行“标识、封装和操纵”的能力,即标识、封装和操纵关注点的能力。是处理复杂性的一个原则。由于关注点混杂在一起会导致复杂性大大增加,所以能够把不同的关注点分离开来,分别处理就是处理复杂性的一个原则,一种方法。
关注点分离是面向对象的程序设计的核心概念。分离关注点使得解决特定领域问题的代码从业务逻辑中独立出来,业务逻辑的代码中不再含有针对特定领域问题代码的调用(将针对特定领域问题代码抽象化成较少的程式码,例如将代码封装成function或是class),业务逻辑同特定领域问题的关系通过侧面来封装、维护,这样原本分散在整个应用程序中的变动就可以很好的管理起来。

具有 then 方法的鸭子类型

根据一个值的形态(具有哪些属性)对这个值的类型做出一些假定。这种类型检查(type check)一般用术语鸭子类型(duck typing)来表示——“如果它看起来像只鸭子,叫起来像只鸭子,那它一定就是只鸭子”

在 ES6 之前,社区已经有一些著名的非 Promise 库恰好有名为 then(..) 的方 法。这些库中有一部分选择了重命名自己的方法以避免冲突(这真糟糕!)。而其他的那 些库只是因为无法通过改变摆脱这种冲突,就很不幸地被降级进入了“与基于 Promise 的 编码不兼容”的状态。

Promise API 概述

new Promise(..) 构造器

1
2
3
4
var p = new Promise( function(resolve,reject){ 
// resolve(..)用于决议/完成这个promise
// reject(..)用于拒绝这个promise
} );

then(..) 和 catch(..)

then(..) 接受一个或两个参数:第一个用于完成回调,第二个用于拒绝回调。

个拒绝回调作为参数,并自动替换默认完成 回调。换句话说,它等价于 then(null,..):

Promise.all([ .. ]) 和 Promise.race([ .. ])

对 Promise.all([ .. ]) 来说,只有传入的所有 promise 都完成,返回 promise 才能完成。 如果有任何 promise 被拒绝,返回的主 promise 就立即会被拒绝

对 Promise.race([ .. ]) 来说,只有第一个决议的 promise(完成或拒绝)取胜,并且其 决议结果成为返回 promise 的决议。

小结

Promise 非常好,请使用。它们解决了我们因只用回调的代码而备受困扰的控制反转问题。

它们并没有摈弃回调,只是把回调的安排转交给了一个位于我们和其他工具之间的可信任 的中介机制。

Promise 链也开始提供(尽管并不完美)以顺序的方式表达异步流的一个更好的方法,这 有助于我们的大脑更好地计划和维护异步 JavaScript 代码。