This repository has been archived by the owner on Jan 24, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpromise.go
124 lines (113 loc) · 2.56 KB
/
promise.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
114
115
116
117
118
119
120
121
122
123
124
package xgraph
import (
"fmt"
"sort"
"strings"
)
// Promise is a future
type Promise struct {
fun func(FinishHandler, FailHandler)
started, finished bool
err error
sfs []FinishHandler
efs []FailHandler
}
// Then registers callbacks and starts the Promise if it has not been already started.
// If the Promise has already completed, the success/failure handler is immediately called with the resu;t.
// This is like Promise.then in JavaScript.
func (p *Promise) Then(success FinishHandler, failure FailHandler) {
if p.finished {
if p.err == nil {
if success != nil {
success()
}
} else {
if failure != nil {
failure(p.err)
}
}
} else {
if success != nil {
p.sfs = append(p.sfs, success)
}
if failure != nil {
p.efs = append(p.efs, failure)
}
if !p.started {
p.fun(p.onFinish, p.onFail)
p.started = true
}
}
}
// onFinish is the FinishHandler passed to the promise function
func (p *Promise) onFinish() {
p.finished = true
for _, v := range p.sfs {
v()
}
//save memory
p.sfs = nil
p.efs = nil
}
// onFail is the FailHandler passed to the promise function
func (p *Promise) onFail(err error) {
p.finished = true
p.err = err
for _, v := range p.efs {
v(err)
}
//save memory
p.sfs = nil
p.efs = nil
}
//FinishHandler is a type of function used as a callback for a Promise on success
type FinishHandler func()
//FailHandler is a type of function used as a callback for a Promise on failure
type FailHandler func(error)
//NewPromise returns a *Promise using the given function
func NewPromise(fun func(FinishHandler, FailHandler)) *Promise {
return &Promise{
fun: fun,
sfs: []FinishHandler{},
efs: []FailHandler{},
}
}
// BuildDependencyError is an error indicating that dependencies failed
type BuildDependencyError []string
func (bde BuildDependencyError) Error() string {
return fmt.Sprintf("dependencies failed: (%s)", strings.Join([]string(bde), ","))
}
func newBuildPromise(deps map[string]*Promise) *Promise {
return NewPromise(func(s FinishHandler, f FailHandler) {
fails := make(map[string]struct{})
n := len(deps)
meh := func() {
if n == 0 {
if len(fails) == 0 {
s()
} else {
flst := make([]string, len(fails))
i := 0
for n := range fails {
flst[i] = n
i++
}
sort.Strings(flst)
f(BuildDependencyError(flst))
}
fails = nil
}
}
for i, v := range deps {
name := i
v.Then(func() {
n--
meh()
}, func(error) {
n--
fails[name] = struct{}{}
meh()
})
}
})
}