Async
Regular calls block the handler until the host answers. For long operations (network, file pickers, sending with a wait for the server id) use freshgram.aio: each call goes to the host at once and the answer arrives later.
import freshgramfrom freshgram import aio
@freshgram.on_command("weather")async def weather(event): response = await aio.net.get("https://example.org/weather") await aio.ui.toast(response.text()[:100])asynciodoes not work here: you can only await awaitables fromfreshgram.aio.- At most 32 calls may wait at the same time.
- The same permissions and limits as for synchronous calls.
aio.filesandaio.fsexist only in the async variant.
Helpers
Section titled “Helpers”| Function | What it does |
|---|---|
aio.sleep(seconds) |
waits without blocking; more than 60 seconds raises Invalid, a negative value waits 0 |
aio.time() |
server time |
aio.gather(*awaitables) |
waits for all and returns a list of results in argument order; gather() with no arguments returns []; the first failure is raised, but the other calls keep running |
aio.wait_for(awaitable, timeout) |
waits at most timeout seconds, otherwise TimeoutError. A timeout over 60 is silently cut to 60 (no error); the call itself is not cancelled, its result is dropped |
aio.spawn(coroutine) |
runs a coroutine on the plugin’s loop and returns a Task; an exception in it is written to the plugin log. freshgram.spawn is the same function |
gather, wait_for and spawn accept a coroutine (the result of calling an async def function) or a Future returned by freshgram.aio; anything else raises TypeError.
Future and Task
Section titled “Future and Task”Every freshgram.aio call returns a aio.Future; aio.spawn returns an aio.Task, which is a Future that runs a coroutine. Both can be awaited, and they have these methods:
| Method | Meaning |
|---|---|
done() |
True once the result or an error is known |
result() |
the result, or raises the stored error; RuntimeError("the result is not ready") if not done() |
exception() |
the error, or None |
set_result(value), set_exception(error) |
finish it by hand (ignored if it is already done) |
add_done_callback(function) |
calls function(future) when done, at once if it is already done |
An error from a call (Denied, Invalid, …) is stored in the future and raised by await or result().
task = aio.spawn(refresh()) # background workfirst, second = await aio.gather(aio.net.get(a), aio.net.get(b))done = task.done()A coroutine also starts if you return it from an event handler: the SDK picks up the CoroutineType.
In Wasm
Section titled “In Wasm”The low-level mechanism is the "async": true flag in the request. The host answers with a ticket {"ticket": N}, and the result arrives as a call.result event with the same ticket. The Rust SDK offers call_async and sleep_async; the C SDK offers fg_begin_async/fg_send_async/fg_sleep_async.
