[书籍翻译] 《JavaScript并发编程》第三章 使用Promises实现同步

本文是我翻译《JavaScript Concurrency》书籍第三章 使用Promises实现同步,该书主要以Promises、Generator、Web workers等技术来讲解JavaScript并发编程方面的实践。

完整书籍翻译地址: 。由于能力有限,肯定存在翻译不清楚甚至翻译错误的地方,欢迎朋友们提issue指出,感谢。

Promises几年前就在JavaScript类库中实现了。这一切都始于Promises/A+规范。这些类库的实现都有它们自己的形式,直到最近(确切地说是ES6),Promises规范才被JavaScript语言纳入。如标题那样 - 它帮助我们实现同步原则。

在本章中,我们将首先简单介绍Promises中各种术语,以便更容易理解本章的后面部分内容。然后,通过各种方式,我们将使用Promises来解决目前的一些问题,并让并发处理更容易。准备好了吗?

Promise相关术语

在我们深入研究代码之前,让我们花一点时间确保我们牢牢掌握Promises有关的术语。有Promise实例,但是还有各种状态和方法。如果我们能够弄清楚Promise这些术语,那么后面的章节会更易理解。这些解释简短易懂,所以如果您已经使用过Promises,您可以快速看下这些术语,就当复习下。

Promise

顾名思义,Promise是一种承诺。将Promise视为尚不存在的值的代理。Promise让我们更好的编写并发代码,因为我们知道值会在将来某个时刻存在,并且我们不必编写大量的状态检查样板代码。

状态(State)

Promises总是处于以下三种状态之一:

• 等待:这是Promise创建后的第一个状态。它一直处于等待状态,直到它完成或被拒绝。

• 完成:该Promise值已经处理完成,并能为它提供then()回调函数。

• 拒绝:处理Promise的值出了问题。现在没有数据。

Promise状态的一个有趣特性是它们只转换一次。它们要么从等待状态到完成,要么从等待状态到被拒绝。一旦它们进行了这种状态转换,后面就会锁定在这种状态。

执行器(Executor)

执行器函数负责以某种方式解析值并将处于等待状态。创建Promise后立即调用此函数。它需要两个参数:resolver函数和rejector函数。

解析器(Resolver)

解析器是一个作为参数传递给执行器函数的函数。实际上,这非常方便,因为我们可以将解析器函数传递给另一个函数,依此类推。调用解析器函数的位置并不重要,但是当它被调用时,Promise会进入一个完成状态。状态的这种改变将触发then()回调 - 这些我们将在后面看到。

拒绝器(Rejector)

拒绝器与解析器相似。它是传递给执行器函数的第二个参数,可以从任何地方调用。当它被调用时,Promise从等待状态改变到拒绝状态。这种状态的改变将调用错误回调函数,如果有的话,会传递给then()或catch()。

Thenable

如果对象具有接受完成回调和拒绝回调作为参数的then()方法,则该对象就是Thenable。换句话说,Promise是Thenable。但是在某些情况下,我们可能希望实现特定的解析语义。

完成和拒绝Promises

如果上一节刚刚介绍的几个术语听起来让你困惑,那别担心。从本节开始,我们将看到所有这些Promises术语的应用实践。在这里,我们将展示一些简单的Promise解决和拒绝的示例。

完成Promises

解析器是一个函数,顾名思义,它完成了我们的Promise。这不是完成Promise的唯一方法 - 我们将在后面探索更高级的方式。但到目前为止,这种方法是最常见的。它作为第一个参数传递给执行器函数。这意味着执行器可以通过简单地调用解析器直接完成Promise。但这并不怎么实用,不是吗?

更常见的情况是Promise执行器函数设置即将发生的异步操作 - 例如拨打网络电话。然后,在这些异步操作的回调函数中,我们可以完成这个Promise。在我们的代码中传递一个解析函数,刚开始可能感觉有点违反直觉,但是一旦我们开始使用它们就会发现很有意义。

解析器函数是一个相对Promise来说比较难懂的函数。它只能完成一次Promise。我们可以调用解析器很多次,但只在第一次调用会改变Promise的状态。下面是一个图描述了Promise的可能状态;它还显示了状态之间是如何变化的:

image060.gif

现在,我们来看一些Promise代码。在这里,我们将完成一个promise,它会调用then()完成回调函数:

//我们的Promise使用的执行器函数。 //第一个参数是解析器函数,在1秒后调用完成Promise。 function executor(resolve) { setTimeout(resolve, 1000); } //我们Promise的完成回调函数。 //这个简单地在我们的执行程序函数运行后,停止那个定时器。 function fulfilled() { console.timeEnd('fulfillment'); } //创建promise,并立即运行, //然后启动一个定时器来查看调用完成函数需要多长时间。 var promise = new Promise(executor); promise.then(fulfilled); console.time('fulfillment');

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjgpw.html