-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinternal.go
113 lines (104 loc) · 2.86 KB
/
internal.go
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
/**********************************************************\
* *
* promise/internal.go *
* *
* some internal type & functions. *
* *
* LastModified: Sep 13, 2016 *
* Author: Ma Bingyao <[email protected]> *
* *
\**********************************************************/
package promise
import (
"reflect"
"time"
)
func catch(promise Promise) {
if e := recover(); e != nil {
promise.Reject(NewPanicError(e))
}
}
func afterCall(promise Promise, results []reflect.Value) {
switch len(results) {
case 0:
promise.Resolve(nil)
case 1:
if results[0].IsNil() {
promise.Resolve(nil)
} else {
result := results[0].Interface()
if reason, ok := result.(error); ok && reason != nil {
promise.Reject(reason)
} else {
promise.Resolve(result)
}
}
case 2:
if reason, ok := results[1].Interface().(error); ok && reason != nil {
promise.Reject(reason)
} else if results[0].IsNil() {
promise.Resolve(nil)
} else {
promise.Resolve(results[0].Interface())
}
}
}
func call(promise Promise, computation reflect.Value, x reflect.Value) {
defer catch(promise)
typ := computation.Type()
numin := typ.NumIn()
numout := typ.NumOut()
if numout > 2 {
panic("The out parameters of computation can't be more than 2")
}
switch numin {
case 0:
afterCall(promise, computation.Call([]reflect.Value{}))
case 1:
afterCall(promise, computation.Call([]reflect.Value{x}))
default:
panic("The in parameters of computation can't be more than 1")
}
}
func resolve(next Promise, onFulfilled OnFulfilled, x interface{}) {
if onFulfilled == nil {
next.Resolve(x)
} else {
f := reflect.ValueOf(onFulfilled)
if f.Kind() != reflect.Func {
panic("onFulfilled can't support this type: " +
f.Type().String())
}
call(next, f, reflect.ValueOf(x))
}
}
func reject(next Promise, onRejected OnRejected, e error) {
if onRejected == nil {
next.Reject(e)
} else {
f := reflect.ValueOf(onRejected)
if f.Kind() != reflect.Func {
panic("onRejected can't support this type: " +
f.Type().String())
}
call(next, f, reflect.ValueOf(e))
}
}
func timeout(promise Promise, duration time.Duration, reason ...error) Promise {
next := New()
timer := time.AfterFunc(duration, func() {
if len(reason) > 0 {
next.Reject(reason[0])
} else {
next.Reject(TimeoutError{})
}
})
promise.WhenComplete(func() { timer.Stop() }).Fill(next)
return next
}
func tap(promise Promise, onfulfilledSideEffect func(interface{})) Promise {
return promise.Then(func(v interface{}) (interface{}, error) {
onfulfilledSideEffect(v)
return v, nil
})
}