forked from then/promise
-
Notifications
You must be signed in to change notification settings - Fork 0
/
core.js
99 lines (87 loc) · 2.35 KB
/
core.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
'use strict'
var nextTick = require('./lib/next-tick')
module.exports = Promise
function Promise(fn) {
if (!(this instanceof Promise)) return new Promise(fn)
if (typeof fn !== 'function') throw new TypeError('not a function')
var state = null
var delegating = false
var value = null
var deferreds = []
var self = this
this.then = function(onFulfilled, onRejected) {
return new Promise(function(resolve, reject) {
handle(new Handler(onFulfilled, onRejected, resolve, reject))
})
}
function handle(deferred) {
if (state === null) {
deferreds.push(deferred)
return
}
nextTick(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) {
if (delegating)
return
resolve_(newValue)
}
function resolve_(newValue) {
if (state !== null)
return
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.')
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
var then = newValue.then
if (typeof then === 'function') {
delegating = true
then.call(newValue, resolve_, reject_)
return
}
}
state = true
value = newValue
finale()
} catch (e) { reject_(e) }
}
function reject(newValue) {
if (delegating)
return
reject_(newValue)
}
function reject_(newValue) {
if (state !== null)
return
state = false
value = newValue
finale()
}
function finale() {
for (var i = 0, len = deferreds.length; i < len; i++)
handle(deferreds[i])
deferreds = null
}
try { fn(resolve, reject) }
catch(e) { reject(e) }
}
function Handler(onFulfilled, onRejected, resolve, reject){
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null
this.onRejected = typeof onRejected === 'function' ? onRejected : null
this.resolve = resolve
this.reject = reject
}