-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
55 lines (50 loc) · 1.54 KB
/
index.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
var err = new Error('Error: recurses! infinite promise chain detected')
module.exports = function promise (resolver) {
var waiting = { res: [], rej: [] }
var p = {
'then': then,
'catch': function thenCatch (onReject) {
return then(null, onReject)
}
}
try { resolver(resolve, reject) } catch (e) {
p.status = false
p.value = e
}
return p
function then (onResolve, onReject) {
return promise(function (resolve, reject) {
waiting.res.push(handleNext(p, waiting, onResolve, resolve, reject, onReject))
waiting.rej.push(handleNext(p, waiting, onReject, resolve, reject, onReject))
if (typeof p.status !== 'undefined') flush(waiting, p)
})
}
function resolve (val) {
if (typeof p.status !== 'undefined') return
if (val === p) throw err
if (val) try { if (typeof val.then === 'function') return val.then(resolve, reject) } catch (e) {}
p.status = true
p.value = val
flush(waiting, p)
}
function reject (val) {
if (typeof p.status !== 'undefined') return
if (val === p) throw err
p.status = false
p.value = val
flush(waiting, p)
}
}
function flush (waiting, p) {
var queue = p.status ? waiting.res : waiting.rej
while (queue.length) queue.shift()(p.value)
}
function handleNext (p, waiting, handler, resolve, reject, hasReject) {
return function next (value) {
try {
value = handler ? handler(value) : value
if (p.status) return resolve(value)
return hasReject ? resolve(value) : reject(value)
} catch (err) { reject(err) }
}
}