-
Notifications
You must be signed in to change notification settings - Fork 0
/
promise.go
123 lines (100 loc) · 2.82 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
package main
import (
"reflect"
)
// NewPromise creates a Promise with default values. It has the implementation of resolve and reject methods
func NewPromise(callback func(rs func(interface{}), rj func(error))) *Promise {
// Define a empty Promise with default values
p := Promise{}
p.channel = make(chan int)
p.status = PENDING
// Resolves the promise
resolve := func(v interface{}) {
p.status = RESOLVED
p.res = v
}
// Rejects the promise
reject := func(e error) {
p.status = REJECTED
p.err = e
}
go func() {
callback(resolve, reject)
p.channel <- 1
}()
<-p.channel
return &p
}
// Then method returns a Promise. It takes up to two arguments: callback functions for the success and failure cases of the Promise.
func (p *Promise) Then(f ...interface{}) *Promise {
// Check if previous promise is settled
if p.status == PENDING {
return p
}
var r func(r interface{}) (*Promise, interface{}, error)
var e func(err error) (*Promise, interface{}, error)
// Assign value to result callback function
if len(f) >= 1 && f[0] != nil {
r = reflect.ValueOf(f[0]).Interface().(func(r interface{}) (*Promise, interface{}, error))
}
// Assign value to errored callback function
if len(f) >= 2 && f[1] != nil {
e = reflect.ValueOf(f[1]).Interface().(func(err error) (*Promise, interface{}, error))
}
var p1 *Promise
go func() {
// If error found
if p.err != nil {
// If error function does not exist return
if e == nil {
p1 = p
p.channel <- 1
return
}
// If error function does exist
// Get the Promise to be returned, by calling the error callback
p1 = populatePromise(e(p.err))
p.channel <- 1
return
}
// If no error found
// If result callback does not exist return
if r == nil {
p1 = p
p.channel <- 1
return
}
// Get the Promise to be returned, by calling the result callback
p1 = populatePromise(r(p.res))
p.channel <- 1
}()
// Wait for channel and return
<-p.channel
return p1
}
// Catch method returns a Promise and deals with rejected cases only
func (p *Promise) Catch(f ...interface{}) *Promise {
// Check if callback function provided, if not then do nothing
if len(f) == 0 {
return p
}
// Call the Then method with success callback as nil and failure callback as the one provided in this function
return p.Then(
nil,
f[0],
)
}
// Finally Method returns a Promise. When the promise is settled, i.e either fulfilled or rejected, the specified callback function is executed. This provides a way for code to be run whether the promise was fulfilled successfully or rejected once the Promise has been dealt with.
func (p *Promise) Finally(f func()) *Promise {
// Check if previous promise is settled
if p.status == PENDING {
return p
}
go func() {
f()
p.channel <- 1
}()
// Wait for channel and return
<-p.channel
return p
}