Featured image of post 手写 Promise

手写 Promise

搭建基本结构

项目文件结构

1
2
3
4
5
6
.
└── custom
    ├── main.js
    ├── package.json
    └── src
        └── promise.js

promise.js

1
2
3
4
5
6
7
export function Promise(executor) {

}

Promise.prototype.then = function (onResolved, onRejected) {

}

main.js

1
2
3
4
5
6
7
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    resolve('OK')
})

p.then(value => console.log(value), reason => console.log(reason))

package.json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "name": "custom",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "type": "module"
}

初步实现 resolve 和 reject

promise.js

 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
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    const self = this

    function resolve(data) {
        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data
    }

    function reject(data) {
        self.PromiseState = 'rejected'
        self.PromiseResult = data
    }

    // 同步调用执行器
    executor(resolve, reject)
}

Promise.prototype.then = function (onResolved, onRejected) {

}

处理执行器执行产生的异常

promise.js

 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
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    const self = this

    function resolve(data) {
        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data
    }

    function reject(data) {
        self.PromiseState = 'rejected'
        self.PromiseResult = data
    }

    // 同步调用执行器
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function (onResolved, onRejected) {

}

main.js

1
2
3
4
5
6
7
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    throw 'error'
})

p.then(value => console.log(value), reason => console.log(reason))

限制状态只能修改一次

promise.js

 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
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    const self = this

    function resolve(data) {
        if (self.PromiseState !== 'pending') return
        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data
    }

    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
    }

    // 同步调用执行器
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function (onResolved, onRejected) {

}

同步执行单个回调

promise.js

 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
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    const self = this

    function resolve(data) {
        if (self.PromiseState !== 'pending') return

        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data
    }

    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
    }

    // 同步调用执行器
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function (onResolved, onRejected) {
    if (this.PromiseState === 'fulfilled') {
        onResolved(this.PromiseResult)
    }
    if (this.PromiseState === 'rejected') {
        onRejected(this.PromiseResult)
    }
}

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    resolve('OK')
})

p.then(value => {
    console.log('success, msg: ', value)
}, reason => {
    console.log('error, msg: ', reason)
})

异步执行单个回调

promise.js

 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
52
53
54
55
56
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    // 保存回调函数
    this.callback = {}

    const self = this

    function resolve(data) {
        if (self.PromiseState !== 'pending') return

        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data

        // 执行成功的回调
        if (self.callback.onResolved) {
            self.callback.onResolved(data)
        }
    }

    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
        // 执行失败的回调
        if (self.callback.onRejected) {
            self.callback.onRejected(data)
        }
    }

    // 同步调用执行器
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function (onResolved, onRejected) {
    if (this.PromiseState === 'fulfilled') {
        onResolved(this.PromiseResult)
    }
    else if (this.PromiseState === 'rejected') {
        onRejected(this.PromiseResult)
    }
    else if (this.PromiseState === 'pending') {
        // 保存回调函数 -------------------- important
        this.callback = {
            onResolved: onResolved,
            onRejected: onRejected
        }
    }
}

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('success')
        resolve('OK')
    }, 1000)
})

p.then(value => {
    console.log('success, msg: ', value)
}, reason => {
    console.log('error, msg: ', reason)
})

异步执行多个回调

promise.js

 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
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    // 保存回调函数
    this.callbacks = []

    const self = this

    function resolve(data) {
        if (self.PromiseState !== 'pending') return

        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data

        // 执行成功的回调
        self.callbacks.forEach(item => item.onResolved(data))
    }

    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
        // 执行失败的回调
        self.callbacks.forEach(item => item.onRejected(data))
    }

    // 同步调用执行器
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function (onResolved, onRejected) {
    if (this.PromiseState === 'fulfilled') {
        onResolved(this.PromiseResult)
    } else if (this.PromiseState === 'rejected') {
        onRejected(this.PromiseResult)
    } else if (this.PromiseState === 'pending') {
        // 保存回调函数 -------------------- important
        this.callbacks.push({
            onResolved: onResolved,
            onRejected: onRejected
        })
    }
}

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('success')
        resolve('OK')
    }, 1000)
})

p.then(value => {
    console.log('success, msg: ', value)
}, reason => {
    console.log('error, msg: ', reason)
})

p.then(value => {
    console.log('success2, msg: ', value)
}, reason => {
    console.log('error, msg: ', reason)
})

同步状态下 then 方法返回 Promise 对象

promise.js

 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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    // 保存回调函数
    this.callbacks = []

    const self = this

    function resolve(data) {
        if (self.PromiseState !== 'pending') return

        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data

        // 执行成功的回调
        self.callbacks.forEach(item => item.onResolved(data))
    }

    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
        // 执行失败的回调
        self.callbacks.forEach(item => item.onRejected(data))
    }

    // 同步调用执行器
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function (onResolved, onRejected) {
    return new Promise((resolve, reject) => {
        if (this.PromiseState === 'fulfilled') {
            // 处理 onResolved 执行出现异常的情况
            try {
                let result = onResolved(this.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        resolve(v)
                    }, r => {
                        reject(r)
                    })
                } else {
                    resolve(result)
                }
            } catch (e) {
                reject(e)
            }
        } else if (this.PromiseState === 'rejected') {
            onRejected(this.PromiseResult)
        } else if (this.PromiseState === 'pending') {
            // 保存回调函数 -------------------- important
            this.callbacks.push({
                onResolved: onResolved,
                onRejected: onRejected
            })
        }
    })
}

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    resolve('OK')
})

let result = p.then(value => {
    return new Promise((resolve, reject) => {
        resolve('success in new Promise')
    })
}, reason => {
    console.log('error, msg: ', reason)
}).then(value => {
    console.log(value)
})

console.dir(result)

异步状态下 then 方法返回 Promise 对象

promise.js

 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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    // 保存回调函数
    this.callbacks = []

    const self = this

    function resolve(data) {
        if (self.PromiseState !== 'pending') return

        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data

        // 执行成功的回调
        self.callbacks.forEach(item => item.onResolved(data))
    }

    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
        // 执行失败的回调
        self.callbacks.forEach(item => item.onRejected(data))
    }

    // 同步调用执行器
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function (onResolved, onRejected) {
    const self = this
    return new Promise((resolve, reject) => {
        if (this.PromiseState === 'fulfilled') {
            // 处理 onResolved 执行出现异常的情况
            try {
                let result = onResolved(this.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        resolve(v)
                    }, r => {
                        reject(r)
                    }) 
                } else {
                    resolve(result)
                }
            } catch (e) {
                reject(e)
            }
        } else if (this.PromiseState === 'rejected') {
            onRejected(this.PromiseResult)
        } else if (this.PromiseState === 'pending') {
            // 保存回调函数 -------------------- important
            this.callbacks.push({
                onResolved: function () {
                    try {
                        let result = onResolved(self.PromiseResult)
                        if (result instanceof Promise) {
                            result.then(v => {
                                resolve(v)
                            }, r => {
                                reject(r)
                            })
                        } else {
                            resolve(result)
                        }
                    } catch (e) {
                        reject(e)
                    }
                },
                onRejected: function () {
                    try {
                        let result = onRejected(self.PromiseResult)
                        if (result instanceof Promise) {
                            result.then(v => {
                                resolve(v)
                            }, r => {
                                reject(r)
                            })
                        } else {
                            resolve(result)
                        }
                    } catch (e) {
                        reject(e)
                    }
                }
            })
        }
    })
}

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK')
    }, 1000)
})

let result = p.then(value => {
    throw 'ERROR-1'
}, reason => {
    console.log('LEVEL1-ERROR')
})

console.log('immediate: ', result)
setTimeout(() => {
    console.log('timer: ', result)
}, 2000)

Output

1
2
3
4
5
6
immediate:  Promise { PromiseState: 'pending', PromiseResult: null, callbacks: [] }
timer:  Promise {
  PromiseState: 'rejected',
  PromiseResult: 'ERROR-1',
  callbacks: []
}

处理执行 then 方法前 Promise 状态变为 rejected 的情况

修改前

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    // setTimeout(() => {
    reject('ERROR')
    // }, 1000)
})

let result = p.then(value => {
    throw 'ERROR-1'
}, reason => {
    console.log('LEVEL1-ERROR')
}).then(value => {
    console.log('aa')
}, reason => {
    console.log('bb')
})

console.log('immediate: ', result)
setTimeout(() => {
    console.log('timer: ', result)
}, 2000)

Output

1
2
3
LEVEL1-ERROR
immediate:  Promise { PromiseState: 'pending', PromiseResult: null, callbacks: [] }
timer:  Promise { PromiseState: 'pending', PromiseResult: null, callbacks: [] }

从上面代码的执行结果可以看出,此时没有输出 aa 也没有输出 bb。主要原因是当 then 方法执行前 Promise 的状态变为 rejected,此时执行 this.PromiseState === 'rejcted' 里面的代码,但是这些代码没有改变返回的新 Promise 实例的状态,导致被存在新 Promise 实例中的回调函数(输出 aa 的成功回调和输出 bb 的失败回调)一直没有被执行。

修改后

promise.js

  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
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    // 保存回调函数
    this.callbacks = []

    const self = this

    function resolve(data) {
        if (self.PromiseState !== 'pending') return

        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data

        // 执行成功的回调
        self.callbacks.forEach(item => item.onResolved(data))
    }

    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
        // 执行失败的回调
        self.callbacks.forEach(item => item.onRejected(data))
    }

    // 同步调用执行器
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function (onResolved, onRejected) {
    const self = this
    return new Promise((resolve, reject) => {
        if (this.PromiseState === 'fulfilled') {
            // 处理 onResolved 执行出现异常的情况
            try {
                let result = onResolved(this.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        resolve(v)
                    }, r => {
                        reject(r)
                    })
                } else {
                    resolve(result)
                }
            } catch (e) {
                reject(e)
            }
        } else if (this.PromiseState === 'rejected') {
            try {
                let result = onRejected(this.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        resolve(v)
                    }, r => {
                        reject(r)
                    })
                } else {
                    resolve(result)
                }
            } catch (e) {
                reject(e)
            }
        } else if (this.PromiseState === 'pending') {
            // 保存回调函数 -------------------- important
            this.callbacks.push({
                onResolved: function () {
                    try {
                        let result = onResolved(self.PromiseResult)
                        if (result instanceof Promise) {
                            result.then(v => {
                                resolve(v)
                            }, r => {
                                reject(r)
                            })
                        } else {
                            resolve(result)
                        }
                    } catch (e) {
                        reject(e)
                    }
                },
                onRejected: function () {
                    try {
                        let result = onRejected(self.PromiseResult)
                        if (result instanceof Promise) {
                            result.then(v => {
                                resolve(v)
                            }, r => {
                                reject(r)
                            })
                        } else {
                            resolve(result)
                        }
                    } catch (e) {
                        reject(e)
                    }
                }
            })
        }
    })
}

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    // setTimeout(() => {
    reject('ERROR')
    // }, 1000)
})

let result = p.then(value => {
    throw 'ERROR-1'
}, reason => {
    console.log('LEVEL1-ERROR')
}).then(value => {
    console.log('aa')
}, reason => {
    console.log('bb')
})

console.log('immediate: ', result)
setTimeout(() => {
    console.log('timer: ', result)
}, 2000)

Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
LEVEL1-ERROR
aa
immediate:  Promise {
  PromiseState: 'fulfilled',
  PromiseResult: undefined,
  callbacks: []
}
timer:  Promise {
  PromiseState: 'fulfilled',
  PromiseResult: undefined,
  callbacks: []
}

代码重构

优化前

then 方法中多次使用到类似如下的代码,只有一处调用的函数不同(下面的代码中调用的是 onRejected),将该代码封装到一个单独的函数,有利于后期维护、增加可读性。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
try {
    let result = onRejected(this.PromiseResult)
    if (result instanceof Promise) {
        result.then(v => {
            resolve(v)
        }, r => {
            reject(r)
        })
    } else {
        resolve(result)
    }
} catch (e) {
    reject(e)
}

优化后

promise.js

 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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    // 保存回调函数
    this.callbacks = []

    const self = this

    function resolve(data) {
        if (self.PromiseState !== 'pending') return

        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data

        // 执行成功的回调
        self.callbacks.forEach(item => item.onResolved(data))
    }

    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
        // 执行失败的回调
        self.callbacks.forEach(item => item.onRejected(data))
    }

    // 同步调用执行器
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function (onResolved, onRejected) {
    const self = this
    return new Promise((resolve, reject) => {
        function handler(callback) {
            try {
                let result = callback(self.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        resolve(v)
                    }, r => {
                        reject(r)
                    })
                } else {
                    resolve(result)
                }
            } catch (e) {
                reject(e)
            }
        }

        if (this.PromiseState === 'fulfilled') {
            // 处理 onResolved 执行出现异常的情况
            handler(onResolved)
        } else if (this.PromiseState === 'rejected') {
            handler(onRejected)
        } else if (this.PromiseState === 'pending') {
            // 保存回调函数 -------------------- important
            this.callbacks.push({
                onResolved: function () {
                    handler(onResolved)
                },
                onRejected: function () {
                    handler(onRejected)
                }
            })
        }
    })
}

main.js

 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
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK')
    }, 1000)
})

let result = p.then(() => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('ERROR')
        })
    }, 1000)
}, () => {
}).then(() => {
    console.log('SUCCESS')
}, () => {
    console.log('FAILED')
})

console.log('immediate: ', result)
setTimeout(() => {
    console.log('timer: ', result)
}, 2000)

Output

1
2
3
4
5
6
7
immediate:  Promise { PromiseState: 'pending', PromiseResult: null, callbacks: [] }
FAILED
timer:  Promise {
  PromiseState: 'fulfilled',
  PromiseResult: undefined,
  callbacks: []
}

catch 方法、异常穿透、值传递

promise.js

 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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    // 保存回调函数
    this.callbacks = []

    const self = this

    function resolve(data) {
        if (self.PromiseState !== 'pending') return

        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data

        // 执行成功的回调
        self.callbacks.forEach(item => item.onResolved(data))
    }

    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
        // 执行失败的回调
        self.callbacks.forEach(item => item.onRejected(data))
    }

    // 同步调用执行器
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function (onResolved, onRejected) {
    if (typeof onResolved !== 'function') {
        // 实现值传递的关键步骤
        onResolved = value => value
    }
    if (typeof onRejected !== 'function') {
        // error: 由于 throw reason 没有返回值,故不能省略大括号
        // onRejected = reason => throw reason
        
        // 实现异常穿透的关键步骤
        onRejected = reason => {
            throw reason
        }
    }
    const self = this
    return new Promise((resolve, reject) => {
        function handler(callback) {
            try {
                let result = callback(self.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        resolve(v)
                    }, r => {
                        reject(r)
                    })
                } else {
                    resolve(result)
                }
            } catch (e) {
                reject(e)
            }
        }

        if (this.PromiseState === 'fulfilled') {
            // 处理 onResolved 执行出现异常的情况
            handler(onResolved)
        } else if (this.PromiseState === 'rejected') {
            handler(onRejected)
        } else if (this.PromiseState === 'pending') {
            // 保存回调函数 -------------------- important
            this.callbacks.push({
                onResolved: function () {
                    handler(onResolved)
                },
                onRejected: function () {
                    handler(onRejected)
                }
            })
        }
    })
}

Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected)
}

main.js

 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
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        // resolve('OK')
        reject('ERROR')
    }, 1000)
})

let result = p.then(() => console.log(1))
              .then(() => console.log(2))
              .then(() => console.log(3))
              .catch(reason => {
                  console.log(reason) // 异常穿透
              })
              .then(() => 23) // 值传递
              .then()
              .then(value => {
                  console.log(value)
              })

console.log('immediate: ', result)
setTimeout(() => {
    console.log('timer: ', result)
}, 2000)

Output

1
2
3
4
5
6
7
8
immediate:  Promise { PromiseState: 'pending', PromiseResult: null, callbacks: [] }
ERROR
23
timer:  Promise {
  PromiseState: 'fulfilled',
  PromiseResult: undefined,
  callbacks: []
}

实现 Promise.resolve()

在 promise.js 中添加如下代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then(
                v => {
                    resolve(v)
                },
                r => {
                    reject(r)
                })
        } else {
            resolve(value)
        }
    })
}

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import {Promise} from "./src/promise.js";

let result = Promise.resolve(new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('ERROR')
    }, 1000)
}))

console.log('immediate: ', result)
setTimeout(() => {
    console.log('timer: ', result)
}, 2000)

Output

1
2
3
4
5
6
immediate:  Promise { PromiseState: 'pending', PromiseResult: null, callbacks: [] }
timer:  Promise {
  PromiseState: 'rejected',
  PromiseResult: 'ERROR',
  callbacks: []
}

实现 Promise.reject()

在 promise.js 中添加如下代码

1
2
3
4
5
Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason)
    })
}

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import {Promise} from "./src/promise.js";

let result = Promise.reject(new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK')
    }, 1000)
}))

console.log('immediate: ', result)
setTimeout(() => {
    console.log('timer: ', result)
}, 2000)

Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
immediate:  Promise {
  PromiseState: 'rejected',
  PromiseResult: Promise {
    PromiseState: 'pending',
    PromiseResult: null,
    callbacks: []
  },
  callbacks: []
}
timer:  Promise {
  PromiseState: 'rejected',
  PromiseResult: Promise {
    PromiseState: 'fulfilled',
    PromiseResult: 'OK',
    callbacks: []
  },
  callbacks: []
}

实现 Promise.all()

在 promise.js 中添加如下代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
Promise.all = function (promises) {
    return new Promise((resolve, reject) => {
        let count = 0 // 成功执行的 promise 的数目
        let resultArr = [] // 结果数组
        for (let i = 0; i < promises.length; ++i) {
            promises[i].then(
                v => {
                    ++count
                    // 注意不要使用 resultArr.push(v),这可能导致结果乱序
                    resultArr[i] = v
                    if (count === promises.length) {
                        resolve(resultArr)
                    }
                },
                r => {
                    // 只要有一个失败,立刻更改状态
                    reject(r)
                }
            )
        }
    })
}

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import {Promise} from "./src/promise.js";

let p1 = Promise.resolve(new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK1')
    }, 1000)
}))

let p2 = Promise.resolve(new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK2')
    }, 2000)
}))

let p3 = Promise.resolve('OK3')

let result = Promise.all([p1, p2, p3])

console.log('immediate: ', result)
setTimeout(() => {
    console.log('timer: ', result)
}, 2000)

Output

1
2
3
4
5
6
immediate:  Promise { PromiseState: 'pending', PromiseResult: null, callbacks: [] }
timer:  Promise {
  PromiseState: 'fulfilled',
  PromiseResult: [ 'OK1', 'OK2', 'OK3' ],
  callbacks: []
}

实现 Promise.race()

在 promise.js 中添加如下代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; ++i) {
            promises[i].then(
                v => {
                    resolve(v)
                },
                r => {
                    reject(r)
                }
            )
        }
    })
}

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import {Promise} from "./src/promise.js";

let p1 = Promise.resolve(new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK1')
    }, 1000)
}))

let p2 = Promise.resolve(new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK2')
    }, 2000)
}))

let p3 = Promise.resolve('OK3')
let p4 = Promise.resolve('OK4')

let result = Promise.race([p1, p2, p3, p4])

console.log('immediate: ', result)
setTimeout(() => {
    console.log('timer: ', result)
}, 2000)

Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
immediate:  Promise {
  PromiseState: 'fulfilled',
  PromiseResult: 'OK3',
  callbacks: []
}
timer:  Promise {
  PromiseState: 'fulfilled',
  PromiseResult: 'OK3',
  callbacks: []
}

then 方法传入的回调函数异步执行

修改前

下面代码使用自定义的 Promise 执行 main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    resolve('OK')
    console.log(1)
})

p.then(() => {
    console.log(2)
})

console.log(3)

Output

1
2
3
1
2
3

下面代码使用官方的 Promise 执行 main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    resolve('OK')
    console.log(1)
})

p.then(() => {
    console.log(2)
})

console.log(3)

Output

1
2
3
1
3
2

从上面的两种输出结果可以看出我们自己写的 then 方法如果在执行前 Promise 的状态已经不是 pending 时则立刻执行,即同步执行,而官方的则是延迟执行,即异步执行。

修改后

promise.js

  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
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
export function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = null

    // 保存回调函数
    this.callbacks = []

    const self = this

    function resolve(data) {
        if (self.PromiseState !== 'pending') return

        // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
        // 2. 设置对象结果值
        self.PromiseResult = data

        // 异步执行成功的回调
        setTimeout(() => {
            self.callbacks.forEach(item => item.onResolved(data))
        })
    }

    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
        // 异步执行失败的回调
        setTimeout(() => {
            self.callbacks.forEach(item => item.onRejected(data))
        })
    }

    // 同步调用执行器
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function (onResolved, onRejected) {
    if (typeof onResolved !== 'function') {
        // 实现值传递的关键步骤
        onResolved = value => value
    }
    if (typeof onRejected !== 'function') {
        // error: 由于 throw reason 没有返回值,故不能省略大括号
        // onRejected = reason => throw reason

        // 实现异常穿透的关键步骤
        onRejected = reason => {
            throw reason
        }
    }
    const self = this
    return new Promise((resolve, reject) => {
        function handler(callback) {
            try {
                let result = callback(self.PromiseResult);
                if (result instanceof Promise) {
                    result.then(v => {
                        resolve(v)
                    }, r => {
                        reject(r)
                    })
                } else {
                    resolve(result)
                }
            } catch (e) {
                reject(e)
            }
        }

        if (this.PromiseState === 'fulfilled') {
            // 处理 onResolved 执行出现异常的情况
            setTimeout(() => { // 异步执行
                handler(onResolved)
            })

        } else if (this.PromiseState === 'rejected') {
            setTimeout(() => { // 异步执行
                handler(onRejected)
            })
        } else if (this.PromiseState === 'pending') {
            // 保存回调函数 -------------------- important
            this.callbacks.push({
                onResolved: function () {
                    handler(onResolved)
                },
                onRejected: function () {
                    handler(onRejected)
                }
            })
        }
    })
}

Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected)
}

Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then(
                v => {
                    resolve(v)
                },
                r => {
                    reject(r)
                })
        } else {
            resolve(value)
        }
    })
}

Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason)
    })
}

Promise.all = function (promises) {
    return new Promise((resolve, reject) => {
        let count = 0 // 成功执行的 promise 的数目
        let resultArr = [] // 结果数组
        for (let i = 0; i < promises.length; ++i) {
            promises[i].then(
                v => {
                    ++count
                    // 注意不要使用 resultArr.push(v),这可能导致结果乱序
                    resultArr[i] = v
                    if (count === promises.length) {
                        resolve(resultArr)
                    }
                },
                r => {
                    // 只要有一个失败,立刻更改状态
                    reject(r)
                }
            )
        }
    })
}

Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; ++i) {
            promises[i].then(
                v => {
                    resolve(v)
                },
                r => {
                    reject(r)
                }
            )
        }
    })
}

main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import {Promise} from "./src/promise.js";

let p = new Promise((resolve, reject) => {
    resolve('OK')
    console.log(1)
})

p.then(() => {
    console.log(2)
})

console.log(3)

Output

1
2
3
1
3
2

将最终结果封装成一个类

promise.js

  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
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
export class Promise {
    constructor(executor) {
        this.PromiseState = 'pending'
        this.PromiseResult = null

        // 保存回调函数
        this.callbacks = []

        const self = this

        function resolve(data) {
            if (self.PromiseState !== 'pending') return

            // 1. 修改对象的状态
            self.PromiseState = 'fulfilled'
            // 2. 设置对象结果值
            self.PromiseResult = data

            // 异步执行成功的回调
            setTimeout(() => {
                self.callbacks.forEach(item => item.onResolved(data))
            })
        }

        function reject(data) {
            if (self.PromiseState !== 'pending') return
            self.PromiseState = 'rejected'
            self.PromiseResult = data
            // 异步执行失败的回调
            setTimeout(() => {
                self.callbacks.forEach(item => item.onRejected(data))
            })
        }

        // 同步调用执行器
        try {
            executor(resolve, reject)
        } catch (e) {
            reject(e)
        }
    }

    then(onResolved, onRejected) {
        if (typeof onResolved !== 'function') {
            // 实现值传递的关键步骤
            onResolved = value => value
        }
        if (typeof onRejected !== 'function') {
            // error: 由于 throw reason 没有返回值,故不能省略大括号
            // onRejected = reason => throw reason

            // 实现异常穿透的关键步骤
            onRejected = reason => {
                throw reason
            }
        }
        const self = this
        return new Promise((resolve, reject) => {
            function handler(callback) {
                try {
                    let result = callback(self.PromiseResult);
                    if (result instanceof Promise) {
                        result.then(v => {
                            resolve(v)
                        }, r => {
                            reject(r)
                        })
                    } else {
                        resolve(result)
                    }
                } catch (e) {
                    reject(e)
                }
            }

            if (this.PromiseState === 'fulfilled') {
                // 处理 onResolved 执行出现异常的情况
                setTimeout(() => { // 异步执行
                    handler(onResolved)
                })

            } else if (this.PromiseState === 'rejected') {
                setTimeout(() => { // 异步执行
                    handler(onRejected)
                })
            } else if (this.PromiseState === 'pending') {
                // 保存回调函数 -------------------- important
                this.callbacks.push({
                    onResolved: function () {
                        handler(onResolved)
                    },
                    onRejected: function () {
                        handler(onRejected)
                    }
                })
            }
        })
    }

    catch(onRejected) {
        return this.then(undefined, onRejected)
    }

    static resolve(value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then(
                    v => {
                        resolve(v)
                    },
                    r => {
                        reject(r)
                    })
            } else {
                resolve(value)
            }
        })
    }

    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }

    static all(promises) {
        return new Promise((resolve, reject) => {
            let count = 0 // 成功执行的 promise 的数目
            let resultArr = [] // 结果数组
            for (let i = 0; i < promises.length; ++i) {
                promises[i].then(
                    v => {
                        ++count
                        // 注意不要使用 resultArr.push(v),这可能导致结果乱序
                        resultArr[i] = v
                        if (count === promises.length) {
                            resolve(resultArr)
                        }
                    },
                    r => {
                        // 只要有一个失败,立刻更改状态
                        reject(r)
                    }
                )
            }
        })
    }

    static race(promises) {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < promises.length; ++i) {
                promises[i].then(
                    v => {
                        resolve(v)
                    },
                    r => {
                        reject(r)
                    }
                )
            }
        })
    }
}
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
主题 StackJimmy 设计