自定义 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
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
(function (window) {
const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";

function MyPromise(executor) {
const self = this;
self.status = PENDING;
self.data = undefined;
self.callback = []; // item:{onResolved(),onRejected()}

function resolve(value) {
setTimeout(() => {
if (self.status !== PENDING) { return; }
self.status = RESOLVED;
self.data = value;
if (self.callback.length > 0) {
self.callback.forEach(item => {
item.onResolved(self.data);
})
}
})
}

function reject(reason) {
setTimeout(() => {
if (self.status !== PENDING) { return; }
self.status = REJECTED;
self.data = reason;
if (self.callback.length > 0) {
self.callback.forEach(item => {
item.onRejected(self.data);
})
}
})
}

try {
executor(resolve, reject);
} catch (error) {
resolve(error);
}
}

MyPromise.prototype.then = function (onResolved, onRejected) {
const self = this;

onResolved = typeof onResolved === "function" ? onResolved : value => value;
onRejected = typeof onRejected === "function" ? onRejected : reason => { throw reason };


return new MyPromise((resolve, reject) => {

function handle(callback) {
try {
const result = callback(self.data);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}

if (self.status === PENDING) {
self.callback.push({
onResolved() {
handle(onResolved);
},
onRejected() {
handle(onRejected);
}
})
} else if (self.status === RESOLVED) {
setTimeout(() => {
handle(onResolved);
})
} else {
setTimeout(() => {
handle(onRejected);
})
}
})
}
MyPromise.prototype.catch = function (onRejected) {
this.then(undefined, onRejected);
}

MyPromise.resolve = function (value) {
return new MyPromise((resolve, reject) => {
if (value instanceof MyPromise) {
value.then(resolve, reject);
} else {
resolve(value);
}
})
}
MyPromise.reject = function (reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
})
}

MyPromise.all = function (promises) {
const resultValue = new Array(promises.length);
let resultCount = 0;

return new MyPromise((resolve, reject) => {
promises.forEach((p, index) => {
MyPromise.resolve(p).then(
value => {
resultCount += 1;
resultValue[index] = value;
if (resultCount === promises.length) {
resolve(resultValue);
}
},
reason => {
reject(reason)
}
);
})
})
}

MyPromise.race = function (promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(p => {
MyPromise.resolve(p).then(resolve, reject);
})
})
}

MyPromise.delayResolve = function (value, time = 0) {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
if (value instanceof MyPromise) {
value.then(resolve, reject);
} else {
resolve(value);
}
}, time)
})
}

MyPromise.delayReject = function (reason, time = 0) {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
reject(reason);
}, time)
})
}

window.MyPromise = MyPromise;
})(window)

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script src="./MyPromise.js"></script>
<script>
const p = new MyPromise((resolve, reject) => {
// resolve(1);
reject(2);
console.log("同步代码");
});

const p1 = MyPromise.delayResolve("ok");
const p2 = MyPromise.delayReject("fuck", 200);
const p3 = MyPromise.resolve(MyPromise.delayReject("err"));
const n = 1;

MyPromise.race([p2, p3, p1])
.then(
(value) => console.log("onResolved", value),
(reason) => {
console.log("onRejected", reason);
throw 404;
}
)
.then((value) => console.log("onResolved", value))
.catch((reason) => console.log("onRejected", reason));
</script>

版权声明:本文作者为「Andy8421」.本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!