Skip to content
Draft

Async

Draft supports async/await for non-blocking operations.

Mark an action as async:

action fetch_data(@url: String) -> async Result<String, Error>
@response = http#get(@url)?
return ok(@response#body)
fin action.

Use await to wait for an async result:

action main()
@result = await fetch_data("https://api.example.com/data")
match @result
when ok then write(@result#value)
when err then write("Error: " + @result#error#message)
fin match.
fin action.

Create async blocks:

action main()
@future = async
@data = fetch_data("https://api.example.com/data")
return @data
fin async.
@result = await @future
fin action.

Run multiple async operations concurrently:

action main()
@future1 = async fetch_data("https://api.example.com/users")
@future2 = async fetch_data("https://api.example.com/posts")
@future3 = async fetch_data("https://api.example.com/comments")
@users = await @future1
@posts = await @future2
@comments = await @future3
fin action.
action main()
@results = await join(
fetch_data("https://api.example.com/users"),
fetch_data("https://api.example.com/posts"),
fetch_data("https://api.example.com/comments")
)
fin action.
action main
@first = await race(
fetch_from_source_a(),
fetch_from_source_b(),
fetch_from_source_c()
)
fin action.
action main()
@stream = open_stream("wss://example.com/ws")
async for @message in @stream
process(@message)
fin for.
fin action.
action main()
@result = await timeout(
fetch_data("https://api.example.com/slow"),
milliseconds(5000)
)
match @result
when ok then write(@result#value)
when err then write("Request timed out")
fin match.
fin action.
action main()
@task = spawn long_running_operation()
@// Do other work...
@task#cancel()
fin action.
action main()
@handle = spawn
@result = fetch_data("https://api.example.com/data")
process(@result)
fin spawn.
@// Continue with other work...
@handle#await()
fin action.
action main()
@channel = Channel<String>::new()
@// Producer
spawn
for @i in 0..10
@channel#send("Message " + string(@i))
fin for.
@channel#close()
fin spawn.
@// Consumer
async for @message in @channel
write(@message)
fin for.
fin action.

Wait on multiple channels:

action main()
@result = select
@channel_a#get() => fn(@msg) => write("A: " + @msg)
@channel_b#get() => fn(@msg) => write("B: " + @msg)
timeout(seconds(5)) => fn() => write("Timeout!")
fin select.
fin action.
action main()
@result = await fetch_data("https://api.example.com/data")
@data = match @result
when ok then @result#value
when err then
write("Error: " + @result#error#message)
return
fin match.
fin match.
fin action.
async action generate_numbers(@count: Int) -> Stream<Int>
for @i in 0..@count
yield @i
fin for.
fin action.
action main()
@stream = generate_numbers(100)
async for @number in @stream
write(string(@number))
fin for.
fin action.

Learn about Generics for type abstraction.