今天咱们来本身手写一个符合PromiseA+规范的Promise库。你们是否是很激动呢??前端
才没有。。
咱们都知道。在如今的前端开发中,Promise这个东西基本上全部的开发中都会用到。es6
那必然有些萌新就会问了,Promise究竟是个什么东西呢。编程
按照规范来讲。Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最先提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。数组
通俗来说。。这个东西就是为了解决咱们日常的回调函数,避免回调地狱的一种解决方案。因此说这个东西你们不只要会用哦,还应该知道他的一些原理。so,咱们一块儿来实现下吧。异步
接下来咱们先看一个简单的Promise。异步编程
这个就是es6标准中的Promise。咱们能够看到,其实Promise就是一个构造函数。函数
这个构造函数中只有一个参数。这个参数在Promise/A+规范中被称为executor(执行者..我以为叫执行器蛮好)。测试
由于这个执行器是为了执行后面的resolve(决定)和reject(拒绝)方法。呃...其实你能够把resolve看做是成功,把reject看作失败。spa
固然了咱们还能够根据本身定义的规则来进行Promise中resolve和reject的调用,不过这是用法,咱们这里就当你们会用了。。对象
而后咱们能够看到,在构造函数的实例p中还有一个then方法。这里咱们就要想了,既然是构造函数的实例上哪必然这个函数是挂在到这个构造函数的原型上。
还有很重要的一点就是咱们能够想一下,在Promise中这个Promise的当前状态是一个问题。在A+规范中规定:一个Promise只有三种状态,咱们看图
什么意思呢。。
大体的意思就是说,一个Promise有且仅有(pending->等待,fulfilled->已执行,rejected->已拒绝)这三种状态中的一种(ps:我曾经看到过一个词->悬而未决用来形容pending也不错 :)。
咱们知道了这些,接下来咱们就来手动实现一个简单的。
继续。。。。
这里咱们要说一下,貌似刚才忘说了。。。
咱们经过这张图来看一下,当目前的状态为pending时。咱们能够将pending状态改变为fulfilled或者rejected中的一种。然而咱们要记住,以前已经提到过Promise的状态必须是三种之一。并且,若是一旦成功就不能失败,一旦失败就不能成功。
接下来咱们依据上面状态的描述来继续、、、
这里当咱们调用resolve和reject的时候咱们须要作出状态判断,只有是pending状态的时候才能够改变状态为其余两种的任意一种,若是不是:例如
咱们处理完了resolve和reject内置的逻辑,这里有一个问题。在开发中,当Promise的执行遇到错误时,会直接变成rejected状态,你们应该都知道,也就是下面的处理。
咱们在Promise的执行过程当中若是捕获到异常,就能够直接调用reject来结束Promise。
接下来咱们看then方法。
这样咱们就实现了一个简单的Promise(才没有。。。这才哪到哪),咱们来试下效果吧。
别忘了导出咱们的Promise。。
咱们看到下面的输出结果,哇!!好激动有没有(才没有激动),我也实现了一个Promise!
可是!有一个问题,咱们是否是弄丢了一个状态???
what??哪一个??仔细想一下好像是‘pending’丢掉了。。
so?那咋办。
有人可能会说了,不是出了成功就是失败吗,为何会有等待状态呢,咱们来思考一下下面的代码。
话说Promise应该都是支持异步的吧?就像上面的代码,异步执行resolve的时候咱们是否是已经吧值给弄丢了?
而且咱们想一下,弄丢这个值得一段时间是否是就是等待态也就是‘pending’的时候。。
因此,咱们要怎么处理这个pending呢?
咱们想一下,在executor中的resolve和reject是否是都会吧咱们传入的值,传到then方法的onfulfilled和onrejected中?另外,咱们在then方法中作了对目前Promise的状态的判断。
因此咱们在then方法中去处理‘pending’状态。
怎么去处理呢?咱们能够在Promise中挂载两个数组。
为何?这两个数组的做用是为了记录pending状态下的onfulfilled和onreject函数。咱们来看then中的代码。
咱们能够看到在pending状态下,这两个数组分别记录了各自对应的then的回调函数,而且保存起来。
咱们来捋一捋思路。
因此说咱们的数组里存的是一个一个的then的回调函数,也就是一个一个function。
因此咱们要在resolve和reject方法触发的时候,去便利咱们的数组而且执行其中的方法,而且呢还要把咱们成功的缘由(self.value)和失败的缘由(self.reason)放到咱们的回调方法中去。说了这么多有点绕。。上代码
这样就解决了异步的问题。咱们再来测试一下。
代码刚开始运行。
2秒后。。。
这时咱们就拿到了异步的值,是否是很开心!(有点,嘿嘿)
再看一下咱们写的所有的代码:
到这里咱们简单了解了Promise的一小部分原理,而且实现了一个很是简单的Promise。今天就先写到这里,在下一章中咱们会继续了解Promise中的then方法是如何链式调用的,以及链式调用中的许多坑。。。
好啦,谢谢你们看到这里。感谢。
再次感谢。