3 ms·
The issue is if you need to add an async call to an existing synchronous code base. If you introduce async in this situation, you’ll probably need to rewrite a
by ddek 5y ago
The issue is if you need to add an async call to an existing synchronous code base. If you introduce async in this situation, you’ll probably need to rewrite a huge chunk of your code to allow it. To prevent inconsistencies, this leads to a practice where programmers return promises or tasks by default, even in synchronous functions; which can cause a myriad of problems beyond simply looking really ugly.
- dragonwriter 5y ago> The issue is if you need to add an async call to an existing synchronous code base. What it seems is needed is a blue function that wraps a red function with (in the simple case, though the actual inplementation needs to be more complicated to identify when thr sinple case applies vs when you have to do something more complicated) a dedicated single-item event loop and returns its result [0] (in async-await, I’d want to have a keyword “sync” used much like “await” but in an otherwise synchronous context to wrap a red function in this blue function.) JS—or at least browsers specifically—might avoid having this, or the tools to do it, to avoid encouraging use of async constructs in a sync context which could kill UI liveness, but for other red/blue async/sync environments it would be useful to have, whether in function or keyword form. [0] “async_to_sync" in this article is an example (for Python, but the general idea would be the same un any environment): https://www.aeracode.org/2018/02/19/python-async-simplified/ https://www.aeracode.org/2018/02/19/python-async-simplified/
- nextaccountic 5y agoIn Rust, calling an async function from a sync function looks like this[0]: block_on(myasyncfn()) This basically repeatedly polls the future returned by the async function, until it completes, and then returns it. (you can also call a full-featured executor like Tokio, but for simple stuff block_on is perfect) My mental model is like this: just like you use await to wait for a future in an async context, you use block_on to wait for a future in a sync context. You only need to call block_on on the top-level future, meaning that myasyncfn() can have a lot of futures underneath. The only thing that won't work is spawning other tasks (new top-level futures that can continue executing even after the future returned by the function completes). Which is actually amazing: after block_on returns, there is no async background tasks lurking on: the program just continues as a normal non-async program. I don't know how async is in other languages, but I guess that every language has something equivalent to block_on? How on Earth you integrate async code into sync code otherwise? As an aside, calling a potentially blocking sync function from an async function is easy too, like this[1]: spawn_blocking(myblockingsyncfn) This spawns a new OS thread (or reuse one from the threadpool dedicated to blocking operations), then run the provided function in there. spawn_blocking returns a future that, when awaited, waits for the function in the other thread to complete, and then returns its value. [0] https://docs.rs/futures/0.3.17/futures/executor/fn.block_on.html https://docs.rs/futures/0.3.17/futures/executor/fn.block_on.... [1] here the exact function to call depends on the executor you use to run the event loop of your async program, but all major ones provides a spawn_blocking API, like https://docs.rs/tokio/1.12.0/tokio/task/fn.spawn_blocking.html https://docs.rs/tokio/1.12.0/tokio/task/fn.spawn_blocking.ht... and https://docs.rs/async-std/1.10.0/async_std/task/fn.spawn_blocking.html https://docs.rs/async-std/1.10.0/async_std/task/fn.spawn_blo...