-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path5-chain.kt
More file actions
85 lines (71 loc) · 2.18 KB
/
5-chain.kt
File metadata and controls
85 lines (71 loc) · 2.18 KB
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
package AsynchronousProgramming
import kotlinx.coroutines.*
interface Chain<T> {
val prev: Chain<T>?
var next: Chain<T>?
operator fun invoke()
fun act(fn: (T, Errback<T>) -> Unit, args: T): Chain<T>
fun forward()
}
fun <T: Any> chain(prev: Chain<T>? = null): Chain<T> = object: Chain<T> {
override val prev = prev
override var next: Chain<T>? = null
private var fn: ((T, Errback<T>) -> Unit)? = null
private lateinit var args: T
override fun invoke() {
println("Reverse from $fn")
prev?.let {
if (fn != null) prev.next = this
prev()
} ?: forward()
}
override fun act(fn: (T, Errback<T>) -> Unit, args: T): Chain<T> {
this.fn = fn
this.args = args
return chain(this)
}
override fun forward() {
println("Forward")
fn?.let {
it(args) {err, data ->
println("Data: $data")
println("Callback from $fn")
if (err == null && next != null) next?.forward()
else println("End at $fn")
}
}
}
}
private fun <T, K> wrapAsync(fn: (T, Errback<K>) -> Unit) = { args: T, cb: Errback<K> ->
GlobalScope.launch {
delay((Math.random() * 1000).toLong())
fn(args, cb)
}
Unit
}
// Asynchronous functions
private val readConfig = wrapAsync { name: String, cb: Errback<String> ->
println("(1) config loaded")
cb(null, name)
}
private val doQuery = wrapAsync { statement: String, cb: Errback<String> ->
println("(2) SQL query executed: $statement")
cb(null, "[{ name: 'Kiev' }, { name: 'Roma' } ]")
}
private val httpGet = wrapAsync { url: String, cb: Errback<String> ->
println("(3) Page retrieved: $url")
cb(null, "<html>Some archaic web here</html>")
}
private val readFile = wrapAsync { path: String, cb: Errback<String> ->
println("(4) File '$path' loaded")
cb(null, "file content")
}
private suspend fun main() {
val chain = chain<String>()
.act(readConfig, "myConfig")
.act(doQuery, "select * from cities")
.act(httpGet, "http://kpi.ua")
.act(readFile, "README.md")
chain()
delay(10000)
}