规范

1.1 “promise”是一个具有then方法的对象或函数,其行为符合此规范。也就是说Promise是一个对象或者函数。
1.2 “thenable”是一个定义then方法的对象或函数,说句人话也就是这个对象必须要拥有then方法。
1.3 “value”是任何合法的JavaScript值(包括undefined、或者promise)。
1.4 promise中的异常需要使用throw语句抛出。
1.5 当promise失败的时候需要给出失败的原因。

状态

1.1 promise必须要拥有三个状态: pending, fulfilled 和 rejected。
1.2 当promise的状态是pending时,他可以变为成功fulfilled或者失败rejected。
1.3 如果promise是成功状态,则他不能转换成任何状态,而且需要一个成功的值,并且这个值不能被改变。
1.4 如果promise是失败状态,则他不能转换成任何状态,而且需要一个失败的原因,并且这个值不能被改变。

then方法说明

1.1 一个promise必须要有一个then方法,而且可以访问promise最终的结果,成功的值。
1.2 then方法需要接收两个参数,onFulfilled 和 onRejected这两个参数是可选参数。

catch方法说明

1.1 一个promise必须要有一个catch方法,而且可以访问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
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

(function () {

function Promise(executor) {
const _self = this;
_self.status = 'pending' // 三个状态 pending / resolved / rejected
_self.result // 存放成功resolve的数据
_self.error // 存放失败reject的数据
_self.onResolvedCallbacks = [] // 存放所有成功的回调
_self.onRejectedCallbacks = [] // 存放所有失败的回调

// resolve reject 接受返回给then函数的 数据、
// resolve 和reject只会触发一次,且只会触发一个,要么成功resolve,要么失败reject
function resolve(res) {
if (_self.status !== 'pending') return
// 更改状态
_self.status = 'fulfilled'
// 缓存结果给then函数使用
_self.result = res

_self.onResolvedCallbacks.forEach(function (fn) {
fn();
})
}

function reject(error) {
if (_self.status !== 'pending') return
_self.status = 'rejected'
_self.error = error
_self.onRejectedCallbacks.forEach(function (fn) {
fn(_self.error);
})
}

// 1. promise 传入的函数立即执行,并接受两个参数 resolve reject
try {
executor(resolve, reject)
} catch (e) {
reject(e);
}
}

// then 方法 接受成功的回调onFulfilled 失败的回调onRejected
Promise.prototype.then = function (onFulfilled, onRejected) {
const _self = this;

// then值穿透, eg: p.then().then(data => {console.log('then2:', data)})
// 第一个then没有传值,需要把数据传入下一个
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (data) { return data; };
onRejected = typeof onRejected === 'function' ? onRejected : function (err) { throw err; };

const nextPromise = new Promise(function (resolve, reject) {
if (_self.status === 'fulfilled') {
try {
const thenFnRes = onFulfilled(_self.result);
// 前一个then入参函数如果return了数据,需要把数据传给下一个then
resolvePromise(nextPromise, thenFnRes, resolve, reject);
} catch (e) {
reject(e)
}
// promise是可以多个then函数
}

if (_self.status === 'rejected') {
try {
const thenFnRes = onRejected(_self.error);
resolvePromise(nextPromise, thenFnRes, resolve, reject);
} catch (e) {
reject(e)
}
}

// 当异步还处于pending状态收集callback
if (_self.status === 'pending') {
_self.onResolvedCallbacks.push(function () {
try {
const thenFnRes = onFulfilled(_self.result);
// 这里需要把 onFulfilled执行的结果作为result resolve给下一个then
resolvePromise(nextPromise, thenFnRes, resolve, reject);
} catch (e) {
reject(e)
}
});

_self.onRejectedCallbacks.push(function () {
try {
const catchFnRes = onRejected(_self.error);
resolvePromise(nextPromise, thenFnRes, resolve, reject);
resolve(catchFnRes)
} catch (e) {
reject(e)
}

});
}
})

// return promise 保证可以链式调用
return nextPromise
}

Promise.prototype.catch = function (errorhandler) {
Promise.then(null, errorhandler)
}


/**
* 处理then入参函数
* @param {*} nextPromise then执行后return的Promise,保证链式调用
* @param {*} thenFnRes then传入函数执行的结果
* @param {*} resolve nextPromise 的 resolve
* @param {*} reject nextPromise 的 reject
*/
function resolvePromise(nextPromise, thenFnRes, resolve, reject) {

// then函数的入参函数没有return数据
if (!thenFnRes) {
resolve(thenFnRes)
return;
}

// 我们的Promise可能会和别人的Promise嵌套使用,官方文档要求,Promise中要书写判断,避免对方Promise不规范产生的影响。
// 比如对方的Promise成功和失败都调用了,或者多次调用了成功。需要使用一个called的变量来表示Promise有没有被调用过。
let called; // 表示Promise有没有被调用过

// then函数返回一个promise,提供链式调用
// 防止then入参函数return返回的这个promise给promise, 这样会重复调用同一个promise
if (nextPromise === thenFnRes) {
return reject(new TypeError('循环引用了,请检查then函数return数据是否正确!'))
}

// 如果返回的是object类型,需要判断是否是promise,还是普通的数据
// 如果是promise需要执行这个promise并拿到resolve的结果返回给下一个then函数
if (typeof thenFnRes === 'object' || typeof thenFnRes === 'function') {
try {
// then 存在是promise
let then = thenFnRes.then;
// 调用then, 这个then函数的this应该指向 thenFnRes
then.call(thenFnRes, function (y) {
if (called) { // 是否调用过
return;
}
called = true;
// 成功的结果,让nextPromise变为成功状态
// y也有可能是promise,需要递归调用 resolvePromise
resolvePromise(nextPromise, y, resolve, reject)
}, function (r) {
if (called) { // 是否调用过
return;
}
called = true;
reject(r);
});

} catch (e) {
if (called) { // 是否调用过
return;
}
called = true;
reject(e);
}
} else {
if (called) { // 是否调用过
return;
}
called = true;
resolve(thenFnRes)
}
resolve(thenFnRes)
}

})();

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

const p = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(1);
}, 1000)
})

p.then(res => {
console.log('then1:', res)
return res + 1
})
.then()
.then(res => {
console.log('then3:', res)
return new new Error()
})
.catch(res => {
console.log('catch:', res)
})

// then1: 1
// then3: 2
// catch: TypeError: (intermediate value) is not a constructor