天天看点

关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示

<a></a>

在我开始promise的“重点”之前,我想我应该给你一点它们如何工作的内貌。一个promise是一个对象——根据Promise/A规范——只需要一个方法:then。then方法带有三个参数:一个成功回调,一个失败回调,和一个前进回调(规范没有要求包括前进回调的实现,但是很多都实现了)。一个全新的promise对象从每个then的调用中返回。

一个promise可以是三种状态之一:未完成的,完成的,或者失败的。promise以未完成的状态开始,如果成功它将会是完成态,如果失败将会是失败态。当一个promise移动到完成态,所有注册到它的成功回调将被调用,而且会将成功的结果值传给它。另外,任何注册到promise的成功回调,将会在它已经完成以后立即被调用。

同样的事情发生在promise移动到失败态的时候,除了它调用的是失败回调而不是成功回调。对包含前进特性的实现来说,promise在它离开未完成状态以前的任何时刻,都可以更新它的progress。当progress被更新,所有的前进回调(progress callbacks)会被传递以progress的值,并被立即调用。前进回调被以不同于成功和失败回调的方式处理;如果你在一个progress更新已经发生以后注册了一个前进回调,新的前进回调只会在它被注册以后被已更新的progress调用。

我们不会进一步深入promise状态是如何管理的,因为那不在规范之内,而且每个实现都有差别。在后面的例子中,你将会看到它是如何完成的,但目前这就是所有你需要知道的。

像前面提到的为异步操作处理回调,是promises的最基本和最普通的用途,让我们将一个标准的回调与一个采用了promise的回调比较一下。

关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示
关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示

我很怀疑只是看到这个例子的话是否有人会真的关心去使用promises。看起来没有什么好处,除了“then”使得在异步操作完成之后的回调函数被调用这件事看起来更加明显。但是即使是这个好处,我们现在有了更多的代码(抽象应该使我们的代码更短,不是吗?)而且promise比标准回调稍微性能差一点。

但是,不要让这阻碍到你。如果这就是promise可以做的最好的事,这篇文章就不会存在了

关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示
关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示

正如你所见,promises的使用使得事情变扁平而且更可读了。这能起作用是因为——像早先提到的——then返回了一个promise,所以你可以将then的调用不停的串连起来。由then返回的promise装载了由调用返回的值。如果调用返回了一个promise(像这个例子中的情形一样),then返回的 promise装载了与你的回调返回的promise所装载的相同值。这内容很多,因此我将帮助你一步一步的理解它

异步操作返回一个promise对象。因此我们在那个promise对象中调用then,并且传给它一个回调函数;then也会返回一个promise。当异步操作结束,它将给promise装上数据。然后(第一次)回调被调用,数据被作为参数传递进去。如果回调不含有返回值,then返回的promise将会立即不带值组装。如果回调返回的不是一个promise,那么then返回的 promise将会立即装载那个数值。如果回调返回一个promise(像例子中的),那么then返回的 promise将等待直到我们回调返回的promise被完全装载。一旦我们回调的 promise被装载,它装载的值(本例中就是data2)将会被提交给then的promise。然后then中的promise装载了data2。等等。听起来有点复杂,但事实上很简单,如果我说的你不能理解,我非常抱歉。我猜我可能不是谈论它的最佳人选。

关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示
关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示

它的例子只是给出了一层深的例子,但它仍是正确的。我们来扩展我前面的例子,使这个看起来容易些。

关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示
关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示

看看上面的代码!他们绝对是对的!它就是一个扁平的结构,但是这里有个问题同样也存在于 我以前从来没有注意过的老的回调例子中:依赖性和复用性。依赖性和复用性是相互关联的可逆类型。一样东西依赖的越少,那么它的复用性就越大。在以上的例子中,handler1依赖handler2,handler2依赖handler3.这就意味着handler1无论出于任何目的都不可在被用除非handler2也呈现出来。假如你不打算重用他们,那么给你的函数命名又有什么意义呢?

最糟糕的的是handler1都不关心在handler2里面发生了什么事情。它压根就不需要handler2除了和它异步工作。因此,让我们消除这些依赖性然后通过用promise使函数更具复用性。

关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示
关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示

这样看起来是不是好多了?假如另外的函数存在的话,现在handler1和handler2都互不相关了。想看看他们是否真的很棒呢?现在handler1可以被用在不需要handler2的情况下了。相反,handler1被操作以后,我们将可以用另一个handler。

关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示
关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示

现在handler1已经从handler2脱离而且可以被用在了更多的情形中,特别是那些由handler2提供的功能而我们又不想用的。这就是复用性!评论家解决代码易读性的唯一方法就是通过消除缩进。我们不想消除缩进仅仅是为了缩进。多层次的缩进仅仅是某些事情错误的标志,问题不一定在它本身。他就像是由脱水引起的头痛。真正的问题是脱水,不是头痛。解决的方法是获得水合物,而不是用一些止痛药。

在前面我提到的文章里,我将promises与events在处理异步操作方面做了比较。遗憾的是,按照那些曾提到过的人在评论里给的说法,我比较的不是很成功。我描述出了promises的力量,接着转到events来描述它们的力量,就像在我的特别项目里用到的那样。没有比较和对比。一位评论者写道(修改了一点语法错误):

他完全正确。事实上我没有比较那两种情况。那篇文章的要点实际在于说明promises不是异步操作的唯一机制,而且在一些情况下,它们也不一定是最好的。在这个评论者指出的情况下,promises当然是最佳的解决办法。我们来看看他说的是什么

以并行的方式执行无数的异步操作非常有用,然后只要在它们之中的每一个结束之后继续执行回调。我们看一个简单的例子。

关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示
关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示
关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示
关于异步Promises一点关于Promises的东西处理回调厄运的金字塔用命名的回调替代命名回调链式回调复用函数并行异步操作值的表示

我相信这真的就是promise的重点。为什么?读一读 Promise/A规范 的第一句“一个promise代表了一个操作的一次完成最终返回的数值。“使它有点明显了,是不是?好吧,即使那就是重点,那也不能阻止我在后面本文中呈现其他人的见解。不管怎么说,我们再多谈论这个思想一点。

    promise的重点是它代表一个操作返回的最终结果值,但使用它们的原因是使同步操作更好的并行。自从异步编程进入此场景,到处都是弹出的回调,以奇怪的方式遮住我们的代码。Promise是一种改变其的方法。Promise允许我们以同步的方式写代码,同时给予我们代码的异步执行。

本文转自艾伦 Aaron博客园博客,原文链接:http://www.cnblogs.com/aaronjs/p/3163786.html,如需转载请自行联系原作者

继续阅读