🛡️
Hogosuru
  • What is Hogosuru?
    • How it works?
    • Minimal requirements to load a wasm
    • Repositories
  • Guides
    • Configure your environment
    • Web API support
    • Create your first project
    • Load and parse a JSON data
    • Create HTML entities and manipulating DOM
      • Create some dynamic content
      • Attach to existing content
      • Modify CSS and attributes
      • Repeat content using template
    • Async work with Promise
    • Network IO: An example with gofiber
    • Observers: Your data always up to date
    • Create a single app with hogosuru
      • Example
Powered by GitBook
On this page
  • A simple example with a background task
  • Chaining Promise
  • Example with 2 long task promise , third will be execute when One is finished:
  • Example with 2 long task promise , third will be execute when All is finished:
  1. Guides

Async work with Promise

PreviousRepeat content using templateNextNetwork IO: An example with gofiber

Last updated 3 years ago

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

The prototype of new is:

promise.New(func(resolvefunc, errfunc js.Value) (interface{}, error)

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:

func main() {
	hogosuru.Init()

	p1, _ := promise.New(func(resolvefunc, errfunc js.Value) (interface{}, error) {
		println("Begin p1")
		w1, _ := promise.SetTimeout(8000)
		w1.Then(func(i interface{}) *promise.Promise {
			println("End p1")
			resolvefunc.Invoke(js.ValueOf("resolve with p1"))
			return nil
		}, nil)

		return nil, nil

	})

	p2, _ := promise.New(func(resolvefunc, errfunc js.Value) (interface{}, error) {
		println("Begin p2")
		w1, _ := promise.SetTimeout(5000)
		w1.Then(func(i interface{}) *promise.Promise {
			println("End p2")
			resolvefunc.Invoke(js.ValueOf("resolve with p2"))
			return nil
		}, nil)

		return nil, nil

	})

	p3, _ := promise.Any(p1, p2)

	p3.Then(func(i interface{}) *promise.Promise {
		if b, ok := i.(string); ok {
			println("First elem response", b)
		}

		return nil
	}, func(e error) {

	})

	ch := make(chan struct{})
	<-ch

}
Begin p1
Begin p2
End p2
First elem response resolve with p2
End p1

Example with 2 long task promise , third will be execute when All is finished:

func main() {
	hogosuru.Init()

	p1, _ := promise.New(func(resolvefunc, errfunc js.Value) (interface{}, error) {
		println("Begin p1")
		w1, _ := promise.SetTimeout(8000)
		w1.Then(func(i interface{}) *promise.Promise {
			println("End p1")
			resolvefunc.Invoke(js.ValueOf("resolve with p1"))
			return nil
		}, nil)

		return nil, nil

	})

	p2, _ := promise.New(func(resolvefunc, errfunc js.Value) (interface{}, error) {
		println("Begin p2")
		w1, _ := promise.SetTimeout(5000)
		w1.Then(func(i interface{}) *promise.Promise {
			println("End p2")
			resolvefunc.Invoke(js.ValueOf("resolve with p2"))
			return nil
		}, nil)

		return nil, nil

	})

	p3, _ := promise.All(p1, p2)

	p3.Then(func(i interface{}) *promise.Promise {
		println("All is finished!")

		return nil
	}, func(e error) {

	})

	ch := make(chan struct{})
	<-ch

}
Begin p1
Begin p2
End p2
End p1
All is finished!

Result: Ok all is perfectly chained like we want

"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 )

The result will be:

The result will be:

👍
🎉
🎉
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Worker