Promise let you create async work . All new Web api are based on promise and you MUST understand the concept. The best reference is always :
I will show you how to work with promise, chained together, or sync it. This part is VERY important to build your Full App with Hogosuru because all Synchronisation is based on it.
A simple example with a background task
func main() {
hogosuru.Init()
fmt.Printf("p1 is launch\n")
p1, _ := promise.New(func(resolvefunc, errfunc js.Value) (interface{}, error) {
fmt.Printf("p1 is calculate\n")
return js.ValueOf("p1 return"), nil
})
fmt.Printf("p1 is in progress....\n")
p1.Then(func(i interface{}) *promise.Promise {
if str, ok := i.(string); ok {
fmt.Printf("p1 is finished with %s\n", str)
}
return nil
}, func(e error) {
fmt.Printf("There was an error %s\n", e.Error())
})
ch := make(chan struct{})
<-ch
}
p1 is launch
p1 is calculate
p1 is in progress....
p1 is finished with p1 return
"Cool it seem that replace goroutine?" => Not really
Demonstration: we inserted a sleep with 2 second (the sleep concept doesn't exist in javascript, it's more than do something after X seconds but we can do in GO):
func main() {
hogosuru.Init()
fmt.Printf("p1 is launch\n")
p1, _ := promise.New(func(resolvefunc, errfunc js.Value) (interface{}, error) {
fmt.Printf("p1 is calculate\n")
time.Sleep(time.Duration(2) * time.Second)
fmt.Printf("p1 end calculate\n")
return js.ValueOf("p1 return"), nil
})
fmt.Printf("p1 is in progress....\n")
p1.Then(func(i interface{}) *promise.Promise {
if str, ok := i.(string); ok {
fmt.Printf("p1 is finished with %s\n", str)
}
return nil
}, func(e error) {
fmt.Printf("There was an error %s\n", e.Error())
})
ch := make(chan struct{})
<-ch
}
Result: "p1 is in progress" seems to be in the wrong place...
p1 is launch
p1 is calculate
p1 end calculate
p1 is in progress....
p1 is finished with p1 return
Promise doesn't work in parallel. It let you do some work in in a range of time and wait for .
But your work is always in ONE thread. It makes it possible to launch pieces of functions in a short time and to wait or leave control to others. But always keep in mind that the time you spend on a loop will be monopolized and not allocated to others until the loop is finished.
As you seed below a "long task" will block a click button until the task is done.
If you refactor with multiple promises and chained, it your click can be handle between all this task.
Chaining Promise
Chaining promise is amazing and can do lots of thing but a little bit complicated to understand
if an interface or an error is return , resolvfunc is automatically call with the good value.
if you return nil,nil, your promise wait indefinite until resolvfunc or errfunc is called.
You can chain easly multiple promise that will be called after the previous has finished.
Just return a new promise at the end of "Then"
Like you see on the graph below, the resolve of promise is call after the end of the execution.
That would mean that the result of promise3 can't be return by promise1
If you want to link the result between linked promise, dont return value , and execute the resolv func at the end of the promise of your choice.
For example: To simulate a waiting promise, you can call resolve your custom promise after the "promise timeout" is finished.
The code will be
p1, _ := promise.New(func(resolvefunc, errfunc js.Value) (interface{}, error) {
//a promise that execute then after 8000 ms
w1, _ := promise.SetTimeout(8000)
w1.Then(func(i interface{}) *promise.Promise {
//8000ms is elapsed we execute the resolv function of p1
resolvefunc.Invoke(js.ValueOf("resolve with p1"))
return nil
}, nil)
return nil, nil
})
Example with 2 long task promise , third will be execute when One is finished:
"So it's not async?": If you come from GO and other low level languages it's not the "true async" but you have to think about dividing your work differently (or use a )