知食记
搜索文档…
实现Promise
参阅这个,层层递进,写得非常好:https://zhuanlan.zhihu.com/p/58428287

极简内核

  1. 1.
    Promise可以new, 所以它是一个类
  2. 2.
    new Promise 传入一个函数,所以constructor是fn
  3. 3.
    fn中会有resolve,我们需要自己定义_resolve传进去作为方法,因此有fn(this._resolve.bind(this))
  4. 4.
    new Promise的实例还可以.then,因此then是Promise的方法
  5. 5.
    内部维护一个callback,作为传入fn的管理,在调用resolve的时候全部遍历执行
1
class Promise {
2
callbacks = [];
3
constructor(fn) {
4
// 内部的_resolve绑定为外部调用
5
fn(this._resolve.bind(this))
6
}
7
then(onFulfilled){
8
this.callbacks.push(onFulfilled)
9
}
10
_resolve(value){
11
this.callbacks.forEach(fn => fn(value))
12
}
13
}
Copied!

链式调用

  1. 1.
    由于promise可以组成then的链式调用,then方法必然也返回promise的实例
  2. 2.
    promise.then是微任务,并不是立即执行,需要增加state作为状态进行执行或者收集的判断
  3. 3.
    promise.then可以传递值给下一个then,因此需要内部维护结果,增加value值
  4. 4.
    promise.then 的 onFulfilled 可以为空,直接resolve之前的值,否知先收集,再统一执行
1
class Promise {
2
callbacks = []
3
state = 'pending'
4
value = undefined
5
6
constructor(fn) {
7
fn(this._resolve.bind(this)
8
}
9
then(onFulfilled = null){
10
// 下面的resolve就是新的实例的this._resolve
11
return new Promise(resolve => {
12
this._handle({ onFulfilled, resolve })
13
})
14
}
15
_handle(callback){
16
if (this.state === 'pending') {
17
this.callbacks.push(callback)
18
return
19
}
20
if (!callback.onFulfilled){
21
// 未设置onFulfilled, resolve 结果给下一个then
22
callback.resolve(this.value)
23
return
24
}
25
const ret = callback.onFulfilled(this.value)
26
callback.resolve(ret)
27
}
28
_resolve(value) {
29
// 先切换状态,这样handle里面的判断不会影响
30
this.state = 'fulfilled'
31
this.value = value
32
// 一个实例的所有callbacks执行完
33
this.callbacks.foreach(callback => this._handle(callback))
34
}
35
}
Copied!

错误处理

  1. 1.
    增加reject
  2. 2.
    onRejected也可以为空
  3. 3.
    即使是有rejected,那也只是设置状态,之前的callback依然要遍历执行完
1
class Promise{
2
state = 'pending'
3
callbacks = []
4
value = undefined
5
constructor(fn){
6
fn(this._resolve.bind(this), this._reject.bind(this)
7
}
8
_resolve(value){
9
this.state = 'fullfiled'
10
this.value = value
11
this.callbacks.foreach(callback => this._handle(callback))
12
}
13
_reject(error){
14
this.state = 'rejected'
15
this.value = error
16
this.callbacks.foreach(callback => this._handle(callback))
17
}
18
_handle(callback){
19
if( this.state === 'pending') {
20
this.callbacks.push(callback)
21
return
22
}
23
24
let cb = this.state === 'fullfilled' ? callback.onFulfilled : callback.onRejected
25
if (!cb) {
26
// 没定义 onFulfilled 或者 onRejected
27
cb = this.state === 'fullfilled' ? callback.resolve : callback.reject
28
cb(this.value)
29
return
30
}
31
const ret = cb()
32
cb(ret)
33
}
34
then(onFulfilled = null, onRejected = null){
35
return new Promise((resolve, reject) => {
36
this._handle(onFulfilled, onRejected, resolve, reject)
37
}
38
}
39
}
Copied!

catch

  1. 1.
    catch也是接收一个函数
  2. 2.
    catch会挂载一个onError, 然后注册到then作为下一个微任务执行
  3. 3.
    为什么class是一个callbacks数组。这里就是callback数组会有两个callback了。一个是then注册的,一个是catch注册的。其他的then都是注册一个新的实例
1
class Promise{
2
state = 'pending'
3
callbacks = []
4
value = undefined
5
constructor(fn){
6
fn(this._resolve.bind(this), this._reject.bind(this)
7
}
8
_resolve(value){
9
this.state = 'fullfiled'
10
this.value = value
11
this.callbacks.foreach(callback => this._handle(callback))
12
}
13
_reject(error){
14
this.state = 'rejected'
15
this.value = error
16
this.callbacks.foreach(callback => this._handle(callback))
17
}
18
_handle(callback){
19
if( this.state === 'pending') {
20
this.callbacks.push(callback)
21
return
22
}
23
24
let cb = this.state === 'fullfilled' ? callback.onFulfilled : callback.onRejected
25
if (!cb) {
26
// 没定义 onFulfilled 或者 onRejected
27
cb = this.state === 'fullfilled' ? callback.resolve : callback.reject
28
cb(this.value)
29
return
30
}
31
const ret = cb()
32
cb(ret)
33
}
34
then(onFulfilled = null, onRejected = null){
35
// 每次 then 都会创建新的 Promise 实例
36
return new Promise((resolve, reject) => {
37
this._handle(onFulfilled, onRejected, resolve, reject)
38
}
39
}
40
catch(onError){
41
// onFulfill为null,仅在onReject里面被调用
42
return this.then(null, onError)
43
}
44
}
Copied!

实现静态方法

  1. 1.
    Promise.resolve对于一个promise实例,会直接返回该实例,因为它自身就有then方法
  2. 2.
    Promise.resolve对于一个对象属性then为函数的,会创建新Promise实例,把这个函数then 传入resolve
  3. 3.
    Promise.resolve对于一个值(即使是函数),会创建新Promise实例,并resolve这个值
thenable函数为:A = { then : function(onFulfilled, onRejected){...}}
1
class Promise {
2
static resolve(value) {
3
if(value && value instanceof Promise){
4
return value
5
} else if( value && typeof value === 'object' && typeof value.then === 'function') {
6
const then = value.then
7
return new Promise( resolve => then(resolve))
8
} else {
9
return new Promise(resolve => resolve(value))
10
}
11
}
12
}
Copied!

实现finally

  1. 1.
    finally 不管是onFulfilled 还是 onRejected 都会被调用,因为内部注册到then 上要挂载 两个函数
1
class Promise {
2
static resolve(value) {
3
if(value && value instanceof Promise){
4
return value
5
} else if( value && typeof value === 'object' && typeof value.then === 'function') {
6
const then = value.then
7
return new Promise( resolve => then(resolve))
8
} else {
9
return new Promise(resolve => resolve())
10
}
11
}
12
static reject(value) {
13
if (value && typeof value === 'object' && typeof value.then === 'function') {
14
let then = value.then;
15
return new Promise((resolve, reject) => {
16
then(reject);
17
});
18
19
} else {
20
return new Promise((resolve, reject) => reject(value));
21
}
22
}
23
finally(onDone) {
24
const Promise = this.constructor;
25
return this.then(
26
value => Promise.resolve(onDone()).then(() => value),
27
reason => Promise.resolve(onDone()).then(() => { throw reason })
28
);
29
}
30
}
Copied!