Asynchronous Functions
This chapter is in development
See the reference section on Async
Asynchronous programming is a technique that enables your program to start a potentially long-running task (or a request from a user) and still be able to be responsive to other events while that task runs, rather than having to wait until that task has finished. Once that task has finished, your program is presented with the result.
This is a relatively new concept inherited from other modern languages. It allows to write asynchronous sequential code avoiding callback hell. AsyncFunction
and Await
expressions and their concepts are built on top of Promises framework.
Limitations
The following constructions are supported with Await
:
Set
CompoundExpression
If
Module
,With
_Symbol
or any other singular expressions
What is not supported (by now)
- Loops:
While
,For
,Do
- Tables and maps:
Map
,Table
Side by side comparison
Here is the same code-block using promises and AsyncFunction
temperature = "Loading";
TextView[temperature // Offload]
Then[ParallelSubmitAsync[URLRead["https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t=temperature_2m"]], Function[response,
temperature = ImportByteArray[response["BodyByteArray"], "RawJSON"]["current", "temperature_2m"];
]]
temperature = "";
TextView[temperature // Offload]
AsyncFunction[Null, Module[{response},
temperature = "Loading";
response = ParallelSubmitAsync[URLRead["https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t=temperature_2m"]] // Await;
temperature = ImportByteArray[response["BodyByteArray"], "RawJSON"]["current", "temperature_2m"];
]][]
The things are getting much more readable if you have multiple nested Then
and promises.
Naturally async functions
There are many built-in functions, which by the default return Promise
- FrontFetchAsync
- ChoiceDialogAsync
- SystemDialogInputAsync
ParallelSubmitAsync
ParallelSubmitFunctionAsync
- Any
EventObject
: InputButton and etc
Examples
Be aware of the evaluation context loss after each Await
statement. Provide EvaluationNotebook, EvaluationCell or CurrentWindow if necessary.
Heavy branching
In this example we demonstrate branching, assignments and compound expressions in asynchronous functions:
p1 = Promise[];
p2 = Promise[];
p3 = Promise[];
win = CurrentWindow[];
f = AsyncFunction[Null, With[{},
Speak["Press p1", "Window"->win];
p1 // Await;
Speak["Press p2A or p2B", "Window"->win];
Module[{m = -100},
m = Await[p2];
Speak["Pause 2 seconds", "Window"->win];
PauseAsync[2] // Await;
If[m > 4,
Speak["Press p3", "Window"->win];
m = Await[p3];
];
StringTemplate["Result: ``"][m]
]
]];
Then[f[], Speak];
To simulate async events here we use buttons
Button["p1", EventFire[p1, Resolve, True]]
Button["p2A", EventFire[p2, Resolve, 1]]
Button["p2B", EventFire[p2, Resolve, 5]]
Button["p3", EventFire[p3, Resolve, 10]]