Preempt
Update the browser optimistically before the server responds.
Preempt
Preempt lets the browser update optimistically before the server responds, instead of waiting on the round trip.
The handler behind the first button sleeps for two seconds to simulate a slow operation; hlivekit.PreemptDisableOn disables the button in the browser immediately on click, before the event even reaches the server. The second button has no such binding, so it stays clickable — and quietly queues up multiple pending increments — for the full two seconds.
Click both buttons a few times to see the difference.
Live Demo
Source
package examples
import (
"context"
"time"
l "github.com/SamHennessy/hlive"
. "github.com/SamHennessy/hlive/hhtml"
"github.com/SamHennessy/hlive/hlivekit"
)
// PreemptDemo is a live, interactive instance of the Preempt example, served
// for the "Live Demo" iframe.
func PreemptDemo() *l.Page {
page := l.NewPage()
page.DOM().Title().Add("Preempt Example")
page.DOM().Head().Add(Link(Rel("stylesheet"), Href("https://cdn.simplecss.org/simple.min.css")))
countWith := l.Box(0)
// Forced to a Component (rather than the hhtml Button() tag builder)
// because its click binding is attached after creation.
btnWith := l.C("button", countWith)
btnWith.Add(hlivekit.PreemptDisableOn(l.On("click",
func(_ context.Context, _ l.Event) {
time.Sleep(2 * time.Second)
countWith.Lock(func(v int) int { return v + 1 })
btnWith.Add(l.AttrsOff{"disabled"})
}),
))
countWithout := l.Box(0)
btnWithout := l.C("button", countWithout)
btnWithout.Add(l.On("click",
func(_ context.Context, _ l.Event) {
time.Sleep(2 * time.Second)
countWithout.Lock(func(v int) int { return v + 1 })
}),
)
page.DOM().Body().Add(
Header(
H1("Preempt - Client Side First Code"),
P("Update the client side DOM before the server side."),
),
Main(
P("The handler will sleep for 2 seconds to simulate a long processing time. "+
"The first button will be disabled in the browser first to prevent extra clicks. Now click the "+
"buttons as many times as you can to see the difference"),
"Clicks With: ",
btnWith,
Br(),
"Clicks Without: ",
btnWithout,
),
)
return page
}