手动实现一个Promise

手写一个Promise是面试中常考的重点,所以想要手写一个Promise,我们必须先知道Promise是什么,有那些特点。在其原型上有那些方法,需要哪些参数等等相关信息。。。。下面我们就先来总结一下:

Promise 是一个对象,代表了未来将要发生的事件,用来传递异步操作的消息。

Promise

  • Promise有三种状态:pending(进行中)、fullfilled(成功)、rejected(失败);
  • Promise对象接受一个回掉函数作为参数,该回掉函数接受俩个参数,resolve(成功回调)和reject(失败回调),resolve的参数除了正常值外,还可以是一个Promise对象的实例,reject的参数通常则是一个Error的实例;
  • then方法返回一个Promise实例,并接受俩个参数,即resolve和reject函数;
  • catch方法返回一个新的Promise实例;
  • finally方法不管是Promise是处于fullfilled状态还是rejected状态,都会执行,而且不接受任何参数;
  • Promise.all()方法是将多个Promise对象包装成一个新的Promise对象。该方法的参数可以不是一个数组,但是必须是具有iterator接口的数据类型,其返回值是每个每个Promise的实例。其中只要有一个是rejected状态,整个Promise.all()就会进入到catch中,而要想正常返回值,就必须是所有的Promise都是fullfilled状态。
  • Promise.race()是和Promise.all()相类似,接受同样的参数,但是不同的是,Promise.race()中,只要有一个实例正常返回,该实例就会返回到Promise.race()中;
  • Promise.resolve()方法是将现有参数转化为Promise对象。如果该方法的参数是一个Promise,那么将不会做任何处理,如果参数是个thenable,那么Promise.resolve()会将该对象转化为Promise对象,并且立即执行then方法。如果参数是一个原始值,或者是一个不具备then方法的对象,则Promise.resolve()方法会返回一个新的Promise,状态为fullfilled,其参数作为then方法中resolve的参数。如果Promise.resolve()不带任何参数,会直接返回一个fullfilled状态的Promise对象。是本轮‘事件循环’的结束时执行。而不是下一轮‘事件循环’的开始;
  • Promise.reject()同样是返回一个Promise对象。状态为rejected,无聊参数如何,都将会作为reject的参数返回。

Promise的优点

  1. 统一的异步API:逐步统一各种不同浏览器中异步API,以及不兼容的模式和手法;
  2. 与事件相比:Promise更适合处理一次性的结果,在结果计算出来之前,或者之后,注册回调函数都是可以的,都是可以拿到正确的值。但是Promise不能处理多次触发的事件,链式调用是Promise的另一个优点,而事件却不能链式调用;
  3. 与回调相比:解决了回调地狱的问题。将异步操作以同步的方式表达出来。
  4. Promise的额外好处是更好的错误处理,写起来更轻松,可以重用一些同步工具等。

Promise的缺点

  1. Promise一旦创建,就会立即执行,并且无法终止;
  2. Promise内部抛出的错误,不会暴露到Promise的外部,只有通过错误的回调来检测错误;
  3. 当Promise的状态是pending状态的时候,并不能明确Promise进行到什么阶段;
  4. 当Promise开始执行到回调的时候,实际Promise部分已经执行完成,但是其中抛出的错误对上下文并不友好。

Promise代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
function _Promise (fn) {
const _this = this
_this.state = 'pending' // 保存Promise的状态
_this.value = '' // 保存Promise的值
_this.reason = '' // 保存Promise的reason
_this.onFullfiledCb = [] // 存储then方法中注册的成功回调函数参数
_this.onRejectedCb = [] // 存储then方法中注册的失败回调函数参数
function resolve (value) {
if (_this.state === 'pending') {
_this.state = 'fullfilled'
_this.value = value
setTimeout(function() {
_this.onFullfiledCb.map(item => item(_this.value))
}, 0)
}
}
function reject (reason) {
if (_this.state === 'pending') {
_this.state = 'rejected'
_this.reason = reason
setTimeout(function () {
_this.onRejectedCb.map(item => item(this.reason))
}, 0)
}
}
try {
fn(resolve, reject)
} catch(err) {
reject(err)
}
}
_Promise.prototype.then = function (onFullfiled, onRejected) {
const _self = this
switch(this.state) {
case 'fullfilled':
onFullfiled(self.value)
break
case 'rejected':
onRejected(self.value)
break
default:
onRejected(self.value)

}
}

// 测试
let p = new _Promise((resolve, reject) => {
resolve('我的世界')
})
p.then(res => console.log(res)) // 我的世界
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2015-2022 Lee
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信