You don't really want to block the single thread the JS code is executing on waiting for input so you cannot await an event in the classical sense. What you can do is use callbacks (execute the further logic in the OnClick eventhandler) or you can use Async.FromContinuations to make an Async<'T> out of the callback:

1
2
3
4
5
6
7
//open WebSharper.Html.Client for this

let btn = Button [ Text "Click me!" ]

let clicked =
    Async.FromContinuations <| fun (ok, _, _) ->
        btn.OnClick (fun el ev -> ok ev) |> ignore

and then you can use it in an async block later to "wait" for it like so (really this is the same thing as using callbacks only much nicer because you "linearize" them):

1
2
3
4
5
6
7
//open WebSharper.JavaScript for this

async {
	let! a = clicked
	JS.Alert "Clicked!"
}
|> Async.Start

but you need to do this asynchronously.

By on 7/27/2015 1:38 AM ()

yes, I wanted to avoid callbacks and the "linearized" version seems to be the one I am looking for, thanks. However this is not the full awaiting as entire workflow is started just away so it cannot cover all functional patterns (like recursive calls which returns non-unit values - for example union cases are very common)

Do you have plans to support generators with promises from EC7 (real await pattern)?

I think that we should be able to write following code then

1
2
3
4
5
let reallyWaitingForThis =
	async {
		let! res = awaitable
    	return res
	} |> Async.RunSynchronously

...use what I was really waiting for ...

Does it involve many changes in WebSharper core to support function* (){yield} pattern?

By on 7/28/2015 4:06 PM ()

The thing with Async.RunSynchronously is that it may be possible to implement (note: I haven't looked into ES7 features in detail yet) but even so it would be discouraged to use it as it would have to block the UI thread while the async computation is being finished (actually I'm not sure if it can be implemented at all).

Most of the time, in JS, an Async<unit> is what you have at the end of your application as the last step of a computation will be inserting something into the DOM or sending some data over Ajax or something that only has a side effect. When dealing with async computations we usually end up with something like (pseudocode):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[<JavaScript>]
module Client =

	let LongComputation some params : Async<string> = 
		async { ... }
    
    let Main =
        Div []
        |>! OnAfterRender (fun e ->
            async {
                let! res = LongComputation 1 2
                let t = Text [res]
                e.Append t.Body
            }
            |> Async.Start)
        
let Server =
	let HomePage =
    	Cotnent.Page 
        	{ Page.Default with
            	Body = [Div [ClientSide <@ Client.Main () @>]] }
        

Or, if using UI.Next, something with View.MapAsync id >> Doc.EmbedView at the end.

By on 7/29/2015 1:16 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper