分析Promise实现
# 分析 Promise 内部实现
在介绍Promise之前,首先我们举一个栗子,看下面代码
function success(message) {
console.log(message)
}
function fail(message) {
console.log(message)
}
function readFile(success, fail) {
console.log('文件读取启动了...')
setTimeout(() => {
if (+new Date() % 2 === 0) {
success('success:文件读取成功了')
} else {
fail('fail:文件读取失败了')
}
}, 1000)
}
readFile(success, fail) // 执行 readFile 函数
console.log('end...')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
输出结果:

【分析】
- 这里我们定义了一个
readFile函数,里面用一个setTimeout定时器模拟读取文件得异步操作 - 而后定时器里分情况调用
success或fail函数 - 首先我们需要注意得是,在这里如果我们需要启动定时器,必须执行
readFile(),同时也必须把回调函数一起传进去 - 也就是说,如果
readFile函数内部已经开始执行得时候 - 如果要有结果,此时必定有
success和fail函数 - 简单概括的话,就是在有结果输出的情况下,
readFile函数内部元素压入调用栈开始执行时,success和fail回调函数 必定存在---即已经定义好了 - 至于为什么会用这个栗子开头,请接着往下看....
# 初识 Promise
举个栗子,看下面的代码:
let file = new Promise((resolve, reject) => {
console.log('promise 读取文件开始了...')
setTimeout(() => {
if (+new Date() % 2 === 0) {
resolve('success:文件读取成功了')
} else {
reject('fail:文件读取失败了')
}
}, 1000)
})
setTimeout(() => {
// 3秒之后开始传入回调函数
file
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
})
}, 3000)
console.log('end...')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
输出结果:

【分析】
- 在第一行代码,我们
new了一个Promise对象 - 里面用了一个
1s定时器 模拟 文件读取 的异步操作 - 看输出结果,第一句输出的是
Promise内部的第一行代码,也就是说,new Promise对象时,内部已经开始执行了, 1s之后,分情况调用resolve或reject函数- 我们注意到,此时我们还没有传入回调函数,
resolve和reject只是我们new Promise时定义的形式参数 3s后,我们开始传入回调函数,这时,我们在3s后传入的回调函数执行了并且出现了结果
【思考】我们回想一开始举的例子
readFile函数执行的时候,此时回调函数已经定义好了,并且作为参数传入了readFile函数new Promise的时候,内部已经开始执行,此时我们并未传入回调函数3s之后,我们才传入回调函数,神奇的是最后有结果输出
【提示】这样一对比,你是不是发现了什么
Promise一 创建对象 内部开始执行,此时我们没有传入回调函数- 未来的某段时间里,我们传入回调函数,回调函数可能会执行并且可以取到结果
【分析总结】
- 在
Promise内部,我们new的时候传入的函数应该立即执行 - 因为在未来的某段时间传入回调函数可以取到结果,所以
Promise内部应该有一个变量将 结果 缓存起来了
# 手动实现 Promise
- 我们通过
new创建Promise对象,所以Promise应该是一个函数,同时传入一个函数作为参数,该函数立即执行 Promise有3种状态:pending、fulfilled、rejected(等待中、已成功、已失败),并且状态只能pending->fulfilled(等待中 -> 已成功)或pending->rejected(等待中 -> 已失败),改变之后状态不能再次变化- 内部有变量存储
失败或成功的结果,这里定义为存储变量为data - 同时
Promise可以链式调用传入回调函数,因此还存在变量保存回调函数集合,这里定义 保存成功的变量onResolvedCallback,保存失败的变量onRejectedCallback
let myPromise = (function() {
// 定义变量保存状态的名字
const PENDING = 'pending' //初始状态
const FULFILLED = 'fulfilled' // 成功状态
const REJECTED = 'rejected' // 成功
function Promise(executor) {
this.status = PENDING // 定义变量保存 状态,初始时为 pending
this.data = undefined // 定义变量保存 结果
this.onResolvedCallback = [] // resolve时的回调函数集合
this.onRejectedCallback = [] // reject时的回调函数集合 // 考虑到执行executor的过程中有可能出错,所以我们用try/catch块给包起来,并且在出错后以catch捕获到的值reject掉这个Promise
try {
// 因为new Promise对象时传入一个函数,该函数立即执行
executor(resolve, reject) // 执行executor
} catch (e) {
reject(e)
}
}
return Promise
})()
let p = new myPromise(function(resolve, reject) {
setTimeout(() => {
if (+new Date() % 2 === 0) {
resolve('success:文件读取成功了')
} else {
reject('fail:文件读取失败了')
}
}, 1000)
})
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
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
输出结果

因为我们在内部调用了 resolve 和 reject , 这两个变量在函数内部我们没有定义,所以出错。那我们在内部定义的这两个函数需要处理什么呢?
resolve应该取状态变为成功的 结果,reject应该取状态变为失败的结果。
继续完善代码
let myPromise = (function() {
// 定义变量保存状态的名字
const PENDING = 'pending' //初始状态
const FULFILLED = 'fulfilled' // 成功状态
const REJECTED = 'rejected' // 成功
function Promise(executor) {
this.status = PENDING // 定义变量保存 状态,初始时为 pending
this.data = undefined // 定义变量保存 结果
this.onResolvedCallback = [] // resolve时的回调函数集合
this.onRejectedCallback = [] // reject时的回调函数集合
function resolve(result) {
if (this.status === PENDING) {
// 状态只能是 pending, 才可以执行下面的代码
this.status = FULFILLED // 因为调用 resolve,所以是成功的,所以状态变为 fulfilled
this.data = result // 保存 成功 的结果 // 开始给 谁想要当前 成功的 结果,就执行他们的函数,并且将 成功 的结果传给他们
this.onResolvedCallback.forEach((cb) => cb(this.data))
}
}
function reject(reason) {
// 同上
if (this.status === PENDING) {
this.status = REJECTED
this.data = reason
this.onRejectedCallback.forEach((cb) => cb(this.data))
}
} // 考虑到执行executor的过程中有可能出错,所以我们用try/catch块给包起来,并且在出错后以catch捕获到的值reject掉这个Promise
try {
// 因为new Promise对象时传入一个函数,该函数立即执行
executor(resolve, reject) // 执行executor
} catch (e) {
reject(e)
}
}
return Promise
})()
let p = new myPromise(function(resolve, reject) {
setTimeout(() => {
if (+new Date() % 2 === 0) {
resolve('success:文件读取成功了')
} else {
reject('fail:文件读取失败了')
}
}, 1000)
})
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
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
到这一步,我们刚才分析的内容大部分完成了
如果我们 MDN 上搜索 Promise

- 我们发现
then、catch、finally是Promise类的实例方法 all、race、reject、resolve是Promise类的静态方法- 所以我们根据分析,可以得出如下的 结构
Promise.prototype.then = function() {}
Promise.prototype.catch = function() {}
Promise.all = function() {}
Promise.race = function() {}
Promise.reject = function() {}
Promise.resolve = function() {}
1
2
3
4
5
6
2
3
4
5
6
# Promise.then 方法实现
Promise.then接受两个参数,一个为成功状态的回调函数,一个为失败状态的回调函数- 同时我们可以不传回调函数,这时直接取 上一个处理的结果,不做处理,直接传递到 下一个
# 讲解
- 首先,
then可以链式调用,所以每次都需要返回一个Promise对象
Promise.prototype.then = function (onFulfilled, onRejected) {
return new Promise(function (resolve, reject) {
}
}
1
2
3
4
2
3
4
- 我们通过前面的分析,已经知道
then里面的回调函数可以 在不同时间段给出,此时,当前这个promise可能出现3种状态 (等待中、已成功、已失败),所以分3种情况 处理
Promise.prototype.then = function(onFulfilled, onRejected) {
return new Promise(function(resolve, reject) {
if (self.status == FULFILLED) {
// 已成功
}
if (self.status == REJECTED) {
// 已失败
}
if (self.status === PENDING) {
// 等待中
}
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
- 接下来我们分析,在这
3种情况下应该做什么
# 已成功
- 因为 状态已经变成了
已成功,所以存储了 成功的结果,我们将 成功的结果 作为参数传递给onFulfilled回调函数并执行 - 因为 返回的
promise的状态由onFulfilled回调函数执行的结果决定 - 所以我们开始分析
onFulfilled可能有什么样的结果- 如果抛出异常,
return的Promise就会失败,结果 就是error - 如果回调函数返回不是
Promise,return的Promise就会成功,value就是返回的值 - 如果回调函数返回是
Promise,return的Promise结果就是这个Promise的结果
- 如果抛出异常,
- 上面
3种 结果是什么意思呢?我们以下面的栗子来说明
var p1 = new Promise()
// 1. 如果抛出异常,`return` 的 `Promise` 就会失败,结果 就是 `error`
p1.then(() => {
// 就是有人会这么直接抛出异常,所以 p1 return 的 Promise 状态应该是 已失败
throw 233
})
// 2. 如果回调函数返回不是 `Promise`,`return` 的 `Promise` 就会成功,`value` 就是返回的值
p1.then(() => {
// 直接 return 一个 值,因为没有抛出异常,所以不是 已失败状态,同时 因为有了结果,所以不是 等待中,最后return 的 Promise 只能是 已成功 状态,
return 1433
})
// 3. 如果回调函数返回是 `Promise`,`return` 的 `Promise` 结果就是这个 `Promise` 的结果
p1.then(() => {
// 因为 返回 了 一个 Promise,所以当前状态无法确定,只能通过 返回的 这个 `Promise` 的最后状态来确定
return new Promise(() => {})
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 根据 分析,我们初步实现 已成功 的 内容,因为要用到
Promise的 存储的结果data,所以我们定义一个变量self= this
Promise.prototype.then = function(onFulfilled, onRejected) {
let self = this
return new Promise(function(resolve, reject) {
if (self.status == FULFILLED) {
// 已成功
setTimeout(() => {
try {
// 获取 回调函数执行的结果
var _result = onFulfilled(self.data)
if (_result instanceof Promise) {
// 3. 如果回调函数返回是 `Promise`,`return` 的 `Promise` 结果就是这个 `Promise` 的结果
_result.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
// 2. 如果回调函数返回不是 `Promise`,`return` 的 `Promise` 就会成功,`value` 就是返回的值
resolve(_result)
}
} catch (e) {
// 1. 如果抛出异常,`return` 的 `Promise` 就会失败,结果 就是 `error`
reject(e)
}
})
}
if (self.status == REJECTED) {
// 已失败
}
if (self.status === PENDING) {
// 等待中
}
})
}
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
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
# 问题:为什么 then回调函数必须设置为 setTimeout 的回调?
setTimeout(() => {
// 保证返回的 Promise 是异步
try {
var _result = onFulfilled(self.data)
if (_result instanceof Promise) {
_result.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
resolve(_result)
}
} catch (e) {
reject(e)
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- 保证返回的
Promise是异步 - (这个部分,下次更新)
# 已失败
- 分析的思路和结果与上面的差不多,不做过多分析
- 需要注意的是此时的
_result = onRejected(self.data),调用失败的回调函数
# 等待中
- 因为当前
Promise的状态是 进行中, 所以我们无法得知最后的状态是 - 我们得等到
Promise的 最后状态确定了 ,才能 知道 是调用onFulfilled还是onRejected - 这时候我们通过发布订阅模式,将当前传入的回调函数都保存起来,等到有了结果再进行通知,并把最后状态的结果传给回调函数
Promise.prototype.then = function(onFulfilled, onRejected) {
let self = this
return new Promise(function(resolve, reject) {
if (self.status == FULFILLED) {
// 已成功
setTimeout(() => {
try {
// 获取 回调函数执行的结果
var _result = onFulfilled(self.data)
if (_result instanceof Promise) {
// 3. 如果回调函数返回是 `Promise`,`return` 的 `Promise` 结果就是这个 `Promise` 的结果
_result.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
// 2. 如果回调函数返回不是 `Promise`,`return` 的 `Promise` 就会成功,`value` 就是返回的值
resolve(_result)
}
} catch (e) {
// 1. 如果抛出异常,`return` 的 `Promise` 就会失败,结果 就是 `error`
reject(e)
}
})
}
if (self.status == REJECTED) {
// 已失败
setTimeout(() => {
try {
var _result = onRejected(self.data)
if (_result instanceof Promise) {
_result.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
resolve(_result)
}
} catch (e) {
reject(e)
}
})
}
if (self.status === PENDING) {
// 等待中
self.onResolvedCallback.push(function() {
setTimeout(() => {
try {
var _result = onFulfilled(self.data)
if (_result instanceof Promise) {
_result.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
resolve(_result)
}
} catch (e) {
reject(e)
}
})
})
self.onRejectedCallback.push(function() {
setTimeout(() => {
try {
var _result = onRejected(self.data)
if (_result instanceof Promise) {
_result.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
resolve(_result)
}
} catch (e) {
reject(e)
}
})
})
}
})
}
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
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
- 我们发现有 四个 地方的内容我们重复写了 四遍,所以提取出来就变成了
Promise.prototype.then = function(onFulfilled, onRejected) {
let self = this
return new Promise(function(resolve, reject) {
// 根据指定回调函数处理,根据执行结果,改变 return 的 promise 的状态
function handle(callback) {
try {
var _result = callback(self.data)
if (_result instanceof Promise) {
_result.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
resolve(_result)
}
} catch (e) {
reject(e)
}
}
if (self.status == FULFILLED) {
setTimeout(() => {
handle(onFulfilled)
})
}
if (self.status == REJECTED) {
// 如果当前是 resolved 状态,异步执行 onRejected 并改变 return 的 promise 状态
setTimeout(() => {
handle(onRejected)
})
}
if (self.status === PENDING) {
self.onResolvedCallback.push(function() {
setTimeout(() => {
handle(onFulfilled)
})
})
self.onRejectedCallback.push(function() {
setTimeout(() => {
handle(onRejected)
})
})
}
})
}
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
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
# 透传
- 由于我们调用
.then方法时,可以一个回调函数都不传,此时应当不对最后状态的结果进行处理,直接传递到下一个Promise - 请始终记得,只要没有手动对状态确定的
Promise的结果进行 过处理,Promise的状态就不会再改变
Promise.prototype.then = function(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled == 'function' ? onFulfilled : (value) => value
onRejected =
typeof onRejected == 'function'
? onRejected
: (reason) => {
throw reason
}
let self = this
return new Promise(function(resolve, reject) {
// 根据指定回调函数处理,根据执行结果,改变 return 的 promise 的状态
function handle(callback) {
try {
var _result = callback(self.data)
if (_result instanceof Promise) {
_result.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
resolve(_result)
}
} catch (e) {
reject(e)
}
}
if (self.status == FULFILLED) {
setTimeout(() => {
handle(onFulfilled)
})
}
if (self.status == REJECTED) {
// 如果当前是 resolved 状态,异步执行 onRejected 并改变 return 的 promise 状态
setTimeout(() => {
handle(onRejected)
})
}
if (self.status === PENDING) {
self.onResolvedCallback.push(function() {
setTimeout(() => {
handle(onFulfilled)
})
})
self.onRejectedCallback.push(function() {
setTimeout(() => {
handle(onRejected)
})
})
}
})
}
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
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
- 通过以上分析,我们已经实现了
.then方法
# Promise.catch 方法实现
catch方法,传入一个失败的回调函数,因为需要获取 失败的结果,所以我们直接调用当前Promise的then方法来获取 失败的结果- 同时调用了
.catch之后,还是返回一个Promise对象,并且 下一个Promise的状态由.catch的回调函数 返回值确定 - 在这里人们会存在的一个误解是:调用
.catch之后,以后的Promise状态都是 已失败,这是错误的 - 你需要时刻记得的是:只要你没有用回调函数处理过 已失败 的结果,之后的
Promise状态就是 已失败,只要你 用回调函数处理了 已失败的结果,之后的Promise状态就根据你 回调函数的 结果来 确定。
Promise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected)
}
1
2
3
2
3
# Promise.all 方法实现
Promise.all方法传入一个数组,当数组中有一个 结果是已失败时,最后结果就是已失败,只有当数组中的 所有 结果都是 成功时,该方法才会被确定为已成功的状态- 已成功 的 结果是一个数组
- 需要注意的是,
已成功的 结果数组,和Promise.all传入的数组是相对应得 - 也就是说,传入的第
2个 是 已成功 数组 的 第2个 结果 - 这里我们可以借鉴 我们常遇到的 保证多个
ajax请求都返回了结果 的解决 办法。 - 我们通过一个变量(
successNum)来保存已成功的数量,如果最后该变量的值 和 传入的数组 长度 一样,那就说明 传入的 数组 所有结果都是 已成功 - 遇到 一个执行结果是
已失败,直接返回已失败的状态
【分析】传入的数组可能的情况
[1, '233', new Promise()]- 一是 字符串或数字
- 二是
Promise对象
Promise.all = function(promises) {
let len = promises.length
let successNum = 0
let _result = []
return new Promise((resolve, reject) => {
promises.forEach((p, i) => {
try {
// 针对 Promise 对象
if (p instanceof Promise) {
p.then(
(res) => {
successNum++
_result[i] = res
if (successNum === len) {
resolve(_result)
}
},
(err) => {
reject(err)
}
)
} else {
// 非 Promise 对象
successNum++
_result[i] = p
if (successNum === len) {
resolve(_result)
}
}
} catch (err) {
reject(err)
}
})
})
}
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
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
# Promise.race 方法实现
Promise.race, 传入的是一个数组,谁先有结果,返回的Promise的状态就是该结果的 状态- 该方法和
Promise.all相比,不需要变量 保存 谁已经执行了,只需要遇到哪个执行完成了,直接返回和其结果一样的状态
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
promises.forEach((p, i) => {
try {
if (p instanceof Promise) {
p.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
resolve(p)
}
} catch (err) {
reject(err)
}
})
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Promise.reject 方法实现
- 该方法返回一个
已失败状态 的Promise - 直接通过新建一个
Promise对象,只传入第二个参数,返回一个已失败的Promise
Promise.reject = function(rejected) {
return new Promise((undefined, reject) => {
reject(rejected)
})
}
1
2
3
4
5
2
3
4
5
# Promise.resolve 方法实现
- 该方法返回一个
已成功状态的Promise - 我们同样通过直接返回一个
Promise对象来 获取 返回成功的 状态 - 这里需要注意的是:因为是返回 一个
已成功的状态,但是我们并不能保证 用户传入的 结果最后就是已成功的状态 - 该方法和
Promise.reject不同 - 用户如果传入了一个
Promise对象 作为参数,那我们应该 取 传入的参数结果和状态作为 当前Promise最后返回的结果和状态
Promise.resolve = function(result) {
return new Promise((resolve, reject) => {
try {
// 如果传入的是一个 Promise 类型的变量,取它的状态和结果作为 Promise.resolve 的状态和结果
if (result instanceof Promise) {
result.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
}
resolve(result)
} catch (e) {
reject(e)
}
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 结果
- 发一个最终版和测试用例
const _Promise = (function() {
const PENDING = 'pending' //初始状态
const FULFILLED = 'fulfilled' // 成功状态
const REJECTED = 'rejected' // 失败状态
function Promise(executor) {
var self = this
self.status = PENDING
self.data = undefined
self.onResolvedCallback = []
self.onRejectedCallback = []
function resolve(result) {
if (self.status === PENDING) {
self.status = FULFILLED
self.data = result
self.onResolvedCallback.forEach((cb) => cb(self.data))
}
}
function reject(reason) {
if (self.status === PENDING) {
self.status = REJECTED
self.data = reason
self.onRejectedCallback.forEach((cb) => cb(self.data))
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
Promise.prototype.then = function(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled == 'function' ? onFulfilled : (value) => value
onRejected =
typeof onRejected == 'function'
? onRejected
: (reason) => {
throw reason
}
let self = this
return new Promise(function(resolve, reject) {
// 根据指定回调函数处理,根据执行结果,改变 return 的 promise 的状态
function handle(callback) {
try {
var _result = callback(self.data)
if (_result instanceof Promise) {
_result.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
resolve(_result)
}
} catch (e) {
reject(e)
}
}
if (self.status == FULFILLED) {
setTimeout(() => {
handle(onFulfilled)
})
}
if (self.status == REJECTED) {
// 如果当前是 resolved 状态,异步执行 onRejected 并改变 return 的 promise 状态
setTimeout(() => {
handle(onRejected)
})
}
if (self.status === PENDING) {
self.onResolvedCallback.push(function() {
setTimeout(() => {
handle(onFulfilled)
})
})
self.onRejectedCallback.push(function() {
setTimeout(() => {
handle(onRejected)
})
})
}
})
}
Promise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected)
}
Promise.all = function(promises) {
let len = promises.length
let successNum = 0
let _result = []
return new Promise((resolve, reject) => {
promises.forEach((p, i) => {
try {
if (p instanceof Promise) {
p.then(
(res) => {
successNum++
_result[i] = res
if (successNum === len) {
resolve(_result)
}
},
(err) => {
reject(err)
}
)
} else {
successNum++
_result[i] = p
if (successNum === len) {
resolve(_result)
}
}
} catch (err) {
reject(err)
}
})
})
}
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
promises.forEach((p, i) => {
try {
if (p instanceof Promise) {
p.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
} else {
resolve(p)
}
} catch (err) {
reject(err)
}
})
})
}
Promise.reject = function(rejected) {
return new Promise((undefined, reject) => {
reject(rejected)
})
}
Promise.resolve = function(result) {
return new Promise((resolve, reject) => {
try {
if (result instanceof Promise) {
result.then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
}
resolve(result)
} catch (e) {
reject(e)
}
})
}
return Promise
})()
let p1 = new _Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1 ---> resolve')
}, 1000)
})
let p2 = new _Promise((resolve, reject) => {
setTimeout(() => {
resolve('p2 ---> resolve')
}, 500)
})
let p3 = new _Promise((resolve, reject) => {
setTimeout(() => {
reject('p3 ---> reject')
}, 1500)
})
_Promise
.all([p1, p2, 120, 'hello', p3])
.then((res) => {
console.log('resolve', res)
})
.then(
() => {},
(err) => {
console.log('err', err)
throw ''
}
)
.then(
(res) => {
console.log('res', res)
},
(err) => {
console.log('err', err)
}
)
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
【输出结果】
err p3 ---> reject
err
1
2
2
上次更新: 2021/09/13, 15:11:59