-
Notifications
You must be signed in to change notification settings - Fork 19
/
newPromise.js
110 lines (101 loc) · 3.03 KB
/
newPromise.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
function Promise(fn) {
if (typeof this !== "object")
throw new TypeError("Promises must be constructed via new")
if (typeof fn !== "function")
throw new TypeError("not a function")
var state = "pending"
var value = null
var callbacks = []
var self = this
this.then = function (onFulfilled, onRejected) {
return new self.constructor(function (resolve, reject) {
handle(handlerFactory(onFulfilled, onRejected, resolve, reject))
})
}
function handle(deferred) {
if (state === "pending") {
callbacks.push(deferred)
return
};
(function () {
var cb = state ? deferred.onFulfilled : deferred.onRejected
if (cb === null) {
(state ? deferred.resolve : deferred.reject)(value)
return
}
var ret
try {
ret = cb(value)
} catch (e) {
deferred.reject(e)
return
}
deferred.resolve(ret)
})()
}
function resolve(newValue) {
try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
if (newValue === self)
throw new TypeError("A promise cannot be resolved with itself.")
//如果传入的是一个Promise或是一个thenable对象
if (newValue && (typeof newValue === "object" || typeof newValue === "function")) {
var then = newValue.then
if (typeof then === "function") {
doResolve(then.bind(newValue), resolve, reject)
return
}
}
state = true
value = newValue
finale()
} catch (e) {
reject(e)
}
}
function reject(newValue) {
state = false
value = newValue
finale()
}
function finale() {
for (var i = 0, len = callbacks.length; i < len; i++)
handle(callbacks[i])
callbacks = null
}
doResolve(fn, resolve, reject)
}
function handlerFactory(onFulfilled, onRejected, resolve, reject) {
return {
onFulfilled: typeof onFulfilled === "function" ? onFulfilled : null,
onRejected: typeof onRejected === "function" ? onRejected : null,
resolve: resolve,
reject: reject
}
}
/**
* Take a potentially misbehaving resolver function and make sure
* onFulfilled and onRejected are only called once.
*
* Makes no guarantees about asynchrony.
*/
function doResolve(fn, onFulfilled, onRejected) {
var done = false;
try {
fn(function (value) {
if (done)
return
done = true
onFulfilled(value)
}, function (reason) {
if (done)
return
done = true
onRejected(reason)
})
} catch (ex) {
if (done)
return
done = true
onRejected(ex)
}
}