背景
Promise是为了解决Javascript回调嵌套过多导致回调地狱(callbackhell)而产生的。目前已被纳入了es2015规范,主流浏览器都支持Promise。为了在工作中更好的运用Promise,我们需要理解Promise规范与内部实现机制,下面我们来手动实现一个Promise。
Promise/A+规范
在写代码之前让我们先了解下 Promise/A+规范。
一个promise有三种状态:
- pending:表示初始状态,可以转移到 fullfilled 或者 rejected 状态
- fulfilled:表示操作成功,不可转移状态
- rejected:表示操作失败,不可转移状态
- 必须有一个 then 异步执行方法,then 接受两个参数且必须返回一个promise:
借用这张来自MDN的流程图我们可以清晰的看到 Promise 状态的流转过程。
简单版
下面我们来实现一个简单版的 Promise:
1 | function Promise1(executor){ |
支持异步
现在,我们实现了最简单的 Promise。以上版本的Promise是存在很多问题的。为什么呢?最大的问题是它不支持异步,然而在现实中,Promise绝大多数使用场景都是异步。让我们来为 Promise 加入异步功能。
1 | const PENDING = 'pending'; |
以上代码中,我们做了如下更改:
- 将 Promise 三个状态定义为常量,方便维护
- 对于 Promise resolve和reject 函数执行加入异步处理
- 在Promise.then中返回新的Promise对象,使Promise可以支持链式调用
错误处理以及静态方法
下面让我们来为Promise 添加错误处理以及静态方法:
1 | //错误处理 |
这里有个问题,就是在当我们console.log(Promise1.resolve(‘a’))的时候,我发现打印出来的状态竟然是 pending状态,我猜想原因是应该是resolve中函数异步执行,在当我们console的时候setTimeout中代码未执行,所以我给出的解决方法是将状态变化与赋值移到setTimeout外面,这样就不会产生刚才的问题了,更改后代码长这样:
1 | function resolve(value) { |
总结
经过以上实践,我们成功的手写了一个功能完备的 Promise。这里给我的最大启发是如果我们想学习一个东西,必须深入到它的底层,了解它的运行原理与具体实现方法,并且可以造一个简单的轮子,这样才算我们掌握了该知识点。从前的我对于这一点没有关注的太多,导致在用某个知识点时只是掌握的它的表层用法,在高级一点的使用场景时完全不会运用。以后我会更加注重源码方面的学习,弥补我这方面的不足。